diff --git a/.gitignore b/.gitignore index a61c0463b..d121487ae 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ obj bin test-results TestResults -*.nupkg \ No newline at end of file +*.nupkg +/packages diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config new file mode 100644 index 000000000..67f8ea046 --- /dev/null +++ b/.nuget/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.nuget/NuGet.exe b/.nuget/NuGet.exe new file mode 100644 index 000000000..8dd7e45ae Binary files /dev/null and b/.nuget/NuGet.exe differ diff --git a/.nuget/NuGet.targets b/.nuget/NuGet.targets new file mode 100644 index 000000000..83fe90601 --- /dev/null +++ b/.nuget/NuGet.targets @@ -0,0 +1,136 @@ + + + + $(MSBuildProjectDirectory)\..\ + + + false + + + false + + + true + + + false + + + + + + + + + + + $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) + $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) + + + + + $(SolutionDir).nuget + packages.config + + + + + $(NuGetToolsPath)\NuGet.exe + @(PackageSource) + + "$(NuGetExePath)" + mono --runtime=v4.0.30319 $(NuGetExePath) + + $(TargetDir.Trim('\\')) + + -RequireConsent + -NonInteractive + + "$(SolutionDir) " + "$(SolutionDir)" + + + $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) + $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols + + + + RestorePackages; + $(BuildDependsOn); + + + + + $(BuildDependsOn); + BuildPackage; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Appveyor.yml b/Appveyor.yml new file mode 100644 index 000000000..e7ff4a705 --- /dev/null +++ b/Appveyor.yml @@ -0,0 +1,3 @@ +build: + project: + SQLite.Net.OSS.sln \ No newline at end of file diff --git a/ImplicitChanges.txt b/ImplicitChanges.txt deleted file mode 100644 index 9932e5321..000000000 --- a/ImplicitChanges.txt +++ /dev/null @@ -1,80 +0,0 @@ -76 - [Flags] - public enum CreateFlags - { - None = 0, - ImplicitPK = 1, // create a primary key for field called 'Id' - ImplicitIndex = 2, // create an index for fields ending in 'Id' - AllImplicit = 3, // do both above - - AutoIncPK = 4 // force PK field to be auto inc - } - - -233 - public TableMapping GetMapping (Type type, CreateFlags createFlags = CreateFlags.None) - { - if (_mappings == null) { - _mappings = new Dictionary (); - } - TableMapping map; - if (!_mappings.TryGetValue (type.FullName, out map)) { - map = new TableMapping (type, createFlags); - _mappings [type.FullName] = map; - } - return map; - } - -293 - public int CreateTable(CreateFlags createFlags = CreateFlags.None) - { - return CreateTable(typeof (T), createFlags); - } - -308 - public int CreateTable(Type ty, CreateFlags createFlags = CreateFlags.None) - { - if (_tables == null) { - _tables = new Dictionary (); - } - TableMapping map; - if (!_tables.TryGetValue (ty.FullName, out map)) { - map = GetMapping(ty, createFlags); - - -1436 - public TableMapping (Type type, CreateFlags createFlags = CreateFlags.None) - -1464 - cols.Add (new Column (p, createFlags)); - -1603 - public Column (PropertyInfo prop, CreateFlags createFlags = CreateFlags.None) - { - var colAttr = (ColumnAttribute)prop.GetCustomAttributes (typeof(ColumnAttribute), true).FirstOrDefault (); - - _prop = prop; - Name = colAttr == null ? prop.Name : colAttr.Name; - //If this type is Nullable then Nullable.GetUnderlyingType returns the T, otherwise it returns null, so get the actual type instead - ColumnType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType; - Collation = Orm.Collation (prop); - IsAutoInc = Orm.IsAutoInc (prop); - IsPK = Orm.IsPK (prop) || (((createFlags & CreateFlags.ImplicitPK) == CreateFlags.ImplicitPK) && prop.Name == Orm.ImplicitPkName); - - IsAutoInc = Orm.IsAutoInc(prop) || (IsPK && ((createFlags & CreateFlags.AutoIncPK) == CreateFlags.AutoIncPK)); - Indices = Orm.GetIndices(prop); - if (!Indices.Any() - && !IsPK - && ((createFlags & CreateFlags.ImplicitIndex) == CreateFlags.ImplicitIndex) - && Name.EndsWith(Orm.ImplicitIndexSuffix) - ) - { - Indices = new IndexedAttribute[] {new IndexedAttribute()}; - } - IsNullable = !IsPK; - MaxStringLength = Orm.MaxStringLength (prop); - } - -1643 - public const string ImplicitPkName = "Id"; - public const string ImplicitIndexSuffix = "Id"; \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..65cf1c239 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. diff --git a/Makefile b/Makefile deleted file mode 100644 index df739f167..000000000 --- a/Makefile +++ /dev/null @@ -1,40 +0,0 @@ - -DIST = sqlite-net-$(VER) - -CP = cp -Rf -RM = rm -Rf - -all: examples tests - -examples: - xbuild examples/Stocks/Stocks.csproj - -tests: SQLite.Tests.dll - nunit-console2 SQLite.Tests.dll - -SQLite.Tests.dll: tests/BooleanTest.cs src/SQLite.cs - gmcs tests/BooleanTest.cs src/SQLite.cs -r:NUnit.Framework -target:library -out:SQLite.Tests.dll - -dist: - rm -Rf $(DIST) - rm -Rf $(DIST).zip - mkdir $(DIST) - cp -Rf src/SQLite.cs $(DIST)/ - cp -Rf src/SQLite.MonoTouchAdmin.cs $(DIST)/ - cp -Rf readme.txt $(DIST)/ - rm -Rf $(DIST)/src/.svn - cp -Rf examples $(DIST)/ - rm -Rf $(DIST)/examples/.svn - rm -Rf $(DIST)/examples/Stocks/.svn - rm -Rf $(DIST)/examples/Stocks/bin - rm -Rf $(DIST)/examples/Stocks/obj - rm -Rf $(DIST)/examples/Stocks/*.pidb - rm -Rf $(DIST)/examples/Stocks/*.userprefs - rm -Rf $(DIST)/examples/StocksTouch/.svn - rm -Rf $(DIST)/examples/StocksTouch/bin - rm -Rf $(DIST)/examples/StocksTouch/obj - rm -Rf $(DIST)/examples/StocksTouch/*.pidb - rm -Rf $(DIST)/examples/StocksTouch/*.userprefs - rm -Rf $(DIST)/.DS_Store - zip -9 -r $(DIST).zip $(DIST) - rm -Rf $(DIST) diff --git a/README.mdown b/README.mdown index 5bda0e813..ce71d8dc2 100644 --- a/README.mdown +++ b/README.mdown @@ -1,9 +1,52 @@ +# Fork -# sqlite-net +This is a fork of the original sqlite-net library (https://github.com/praeclarum/sqlite-net), which aims to improve the code quality by using modern technologies such as PCL (portable class library). -sqlite-net is an open source, minimal library to allow .NET and Mono applications to store data in [http://www.sqlite.org SQLite 3 databases]. It is written in C# and is meant to be simply compiled in with your projects. It was first designed to work with [MonoTouch](http://xamarin.com) on the iPhone, but has grown up to work on all the platforms (Mono for Android, .NET, Silverlight, WP7, WinRT, Azure, etc.). +The project will avoid the use of #if-based conditional code and use platform-specific code injection instead. -sqlite-net was designed as a quick and convenient database layer. Its design follows from these *goals*: +I welcome pull requests, but keep in mind that this library is in heavy use and all changes must be: +- Backwards-compatible (don't change database defaults). +- Well tested (please add unit tests). + +# API Changes + +As part of the cleanup there are now some API changes. + +For the most part I hope these are self-explanatory, but here is a non-exhaustive list of changes. + +## SQLiteConnection +You now have to pass in an implementation of ISQlitePlatform in the SQLiteConnectionWithLock and SQLiteConnection constructors. + +I provide ready-made implementations of this class, please see use one(or more) of these [nugets](https://www.nuget.org/profiles/oystein.krog/). + +At the moment these platforms have nugets available: +- Win32 (bundles sqlite binaries for windows, works on both x86 and x64 automatically) (very well tested) +- XamarinIOS (very well tested) +- XamarinAndroid (not very well tested, please give feedback) +- WindowsPhone8 (not very well tested, please give feedback) (contributed by Nick Cipollina, thanks!) +- WindowsRT (not very well tested, please give feedback) (contributed by Nick Cipollina and Micah Lewis, thanks!) +- Generic (well tested) (net4 project without any sqlite3 binaries, requires sqlite installed in the OS) (contributed by James Ottaway) + +Note: +To use the WP8 platform you must install the "SQLite for Windows Phone" VSIX extension. +Then, in the WP8 project, add a reference to it (in the Windows Phone SDK 8.0 / Extensions section of the Add Reference dialog) +If you have problems with signed apps take a look here: https://github.com/oysteinkrog/SQLite.Net-PCL/issues/25 + +## SQliteAsyncConnection +The SQLiteAsyncConnection class now takes a Func in the constructor instead of a path. +This is done because the async classes are now just meant to be wrappers around the normal sqlite connection. + +To use SQLiteAsyncConnection just create an instance of a SQLiteConnectionWithLock and pass in that through a func, e.g.: +new SQLiteAsyncConnection(()=>_sqliteConnectionWithLock); + +Please be aware that the Task.Run pattern used in SQLiteAsyncConnection can be considered an anti-pattern (libraries should not provide async methods unless they are truly async). +This class is maintained for backwards compatability and for use-cases where async-isolation is handy. + +# SQLite.Net + +SQLite.Net is an open source, minimal library to allow .NET and Mono applications to store data in [http://www.sqlite.org SQLite 3 databases]. It is written in C# and is meant to be simply compiled in with your projects. It was first designed to work with [MonoTouch](http://xamarin.com) on the iPhone, but has grown up to work on all the platforms (Mono for Android, .NET, Silverlight, WP7, WinRT, Azure, etc.). + +SQLite.Net was designed as a quick and convenient database layer. Its design follows from these *goals*: * Very easy to integrate with existing projects and with MonoTouch projects. @@ -19,15 +62,18 @@ sqlite-net was designed as a quick and convenient database layer. Its design fol * Not an ADO.NET implementation. This is not a full SQLite driver. If you need that, use [Mono.Data.SQLite](http://www.mono-project.com/SQLite) or [csharp-sqlite](http://code.google.com/p/csharp-sqlite/). +## License +This projected is licensed under the terms of the MIT license. +See LICENSE.TXT ## Meta -This is an open source project that welcomes contributions/suggestions/bug reports from those who use it. If you have any ideas on how to improve the library, please [post an issue here on github](https://github.com/praeclarum/sqlite-net/issues). Please check out the [How to Contribute](https://github.com/praeclarum/sqlite-net/wiki/How-to-Contribute). +This is an open source project that welcomes contributions/suggestions/bug reports from those who use it. If you have any ideas on how to improve the library, please [post an issue here on github](https://github.com/praeclarum/SQLite.Net/issues). Please check out the [How to Contribute](https://github.com/praeclarum/SQLite.Net/wiki/How-to-Contribute). # Example Time! -Please consult the Wiki for, ahem, [complete documentation](https://github.com/praeclarum/sqlite-net/wiki). +Please consult the source code (see unit tests) for more examples. The library contains simple attributes that you can use to control the construction of tables. In a simple stock program, you might use: @@ -59,7 +105,7 @@ Both APIs are explained in the two sections below. Once you have defined your entity, you can automatically generate tables in your database by calling `CreateTable`: - var db = new SQLiteConnection("foofoo"); + var db = new SQLiteConnection(sqlitePlatform, "foofoo"); db.CreateTable(); db.CreateTable(); @@ -76,7 +122,7 @@ Similar methods exist for `Update` and `Delete`. The most straightforward way to query for data is using the `Table` method. This can take predicates for constraining via WHERE clauses and/or adding ORDER BY clauses: - var conn = new SQLiteConnection("foofoo"); + var conn = new SQLiteConnection(sqlitePlatform, "foofoo"); var query = conn.Table().Where(v => v.Symbol.StartsWith("A")); foreach (var stock in query) @@ -109,7 +155,7 @@ will work for you. Once you have defined your entity, you can automatically generate tables by calling `CreateTableAsync`: - var conn = new SQLiteAsyncConnection("foofoo"); + var conn = new SQLiteAsyncConnection(()=>sqliteConnection, "foofoo"); conn.CreateTableAsync().ContinueWith((results) => { Debug.WriteLine("Table created!"); @@ -122,7 +168,7 @@ You can insert rows in the database using `Insert`. If the table contains an aut Symbol = "AAPL" }; - var conn = new SQLiteAsyncConnection("foofoo"); + var conn = new SQLiteAsyncConnection(()=>sqliteConnection, "foofoo"); conn.InsertAsync(stock).ContinueWith((t) => { Debug.WriteLine("New customer ID: {0}", stock.Id); @@ -134,7 +180,7 @@ Querying for data is most straightforwardly done using the `Table` method. This you can add predictates for constraining via WHERE clauses and/or adding ORDER BY. The database is not physically touched until one of the special retrieval methods - `ToListAsync`, `FirstAsync`, or `FirstOrDefaultAsync` - is called. - var conn = new SQLiteAsyncConnection("foofoo"); + var conn = new SQLiteAsyncConnection(()=>sqliteConnection, "foofoo"); var query = conn.Table().Where(v => v.Symbol.StartsWith("A")); query.ToListAsync().ContinueWith((t) => @@ -155,14 +201,3 @@ Another helpful method is `ExecuteScalarAsync`. This allows you to return a scal }); -## Special note on use within Windows Store Apps (Windows 8/WinRT) - -sqlite-net is fully compliant with WinRT Metro-style apps and will pass Microsoft Store validation. - -Please note: - -* Database files will always be created in the path returned by `Windows.Storage.ApplicationData.Current.LocalFolder.Path`. - -* You will need a copy of sqlite3.dll for your app as well. You can get this from sqlite.org with an installer to the SQLite for Windows Runtime SDK. - - diff --git a/SQLite.Net.OSS.sln b/SQLite.Net.OSS.sln new file mode 100644 index 000000000..e68524ebc --- /dev/null +++ b/SQLite.Net.OSS.sln @@ -0,0 +1,468 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30723.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{59584026-7610-4CD5-A74E-D2B0A2E1CE87}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Platform.Win32", "src\SQLite.Net.Platform.Win32\SQLite.Net.Platform.Win32.csproj", "{03799AD1-9FCF-48CB-8E6E-B233DF583B10}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{0C4021EF-617B-4620-ADD3-A702B4F9FA86}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Tests.Win32", "tests\SQLite.Net.Tests.Win32\SQLite.Net.Tests.Win32.csproj", "{BFF4B373-2844-40AD-8994-2BA5AC42AEE0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Platform.Generic", "src\SQLite.Net.Platform.Generic\SQLite.Net.Platform.Generic.csproj", "{F662E15A-8753-468E-A67E-3FCF45F12B89}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Tests.Generic", "tests\SQLite.Net.Tests.Generic\SQLite.Net.Tests.Generic.csproj", "{C129735F-5D4B-40BE-9410-F43E548FFF5E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{49C7015B-F41A-47A6-8200-B925902E74E9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stocks", "examples\Stocks\Stocks.csproj", "{9E5D6B89-B69B-486B-9F7B-406BE8690589}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{5BD976ED-6E22-44A3-A5A1-D6C6633BAADD}" + ProjectSection(SolutionItems) = preProject + .nuget\NuGet.Config = .nuget\NuGet.Config + .nuget\NuGet.exe = .nuget\NuGet.exe + .nuget\NuGet.targets = .nuget\NuGet.targets + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net", "src\SQLite.Net\SQLite.Net.csproj", "{4971D437-0694-4297-A8CC-146CE08C3BD9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Async", "src\SQLite.Net.Async\SQLite.Net.Async.csproj", "{3AB34E91-8E1A-442F-8E66-2494B371A890}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Ad-Hoc|Any CPU = Ad-Hoc|Any CPU + Ad-Hoc|ARM = Ad-Hoc|ARM + Ad-Hoc|iPhone = Ad-Hoc|iPhone + Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator + Ad-Hoc|Mixed Platforms = Ad-Hoc|Mixed Platforms + Ad-Hoc|x64 = Ad-Hoc|x64 + Ad-Hoc|x86 = Ad-Hoc|x86 + AppStore|Any CPU = AppStore|Any CPU + AppStore|ARM = AppStore|ARM + AppStore|iPhone = AppStore|iPhone + AppStore|iPhoneSimulator = AppStore|iPhoneSimulator + AppStore|Mixed Platforms = AppStore|Mixed Platforms + AppStore|x64 = AppStore|x64 + AppStore|x86 = AppStore|x86 + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|iPhone = Debug|iPhone + Debug|iPhoneSimulator = Debug|iPhoneSimulator + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|iPhone = Release|iPhone + Release|iPhoneSimulator = Release|iPhoneSimulator + Release|Mixed Platforms = Release|Mixed Platforms + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|Any CPU.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|ARM.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|x64.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|x86.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|ARM.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|x64.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|x86.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|Any CPU.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|ARM.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|iPhone.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|x64.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|x86.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|Any CPU.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|ARM.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|x64.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|x86.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|ARM.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|x64.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|x86.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|Any CPU.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|ARM.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|iPhone.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|x64.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|x86.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|ARM.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|x64.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|x86.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|Any CPU.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|ARM.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|ARM.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|iPhone.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|x64.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|x64.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|x86.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|x86.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|ARM.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|ARM.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|iPhone.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|x64.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|x64.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|x86.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|x86.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|Any CPU.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|ARM.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|ARM.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|iPhone.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|iPhone.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|x64.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|x64.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|x86.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|x86.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|ARM.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|x64.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|x86.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|Any CPU.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|ARM.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|ARM.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|iPhone.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|x64.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|x64.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|x86.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|x86.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|ARM.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|iPhone.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|x64.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|x64.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|x86.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|x86.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|Any CPU.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|ARM.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|ARM.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|iPhone.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|iPhone.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|x64.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|x64.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|x86.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|x86.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|Any CPU.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|ARM.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|x64.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|x86.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|ARM.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|x64.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|x86.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|Any CPU.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|ARM.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|iPhone.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|x64.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|x86.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|Any CPU.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|ARM.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|x64.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|x86.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|ARM.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|x64.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|x86.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|Any CPU.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|ARM.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|iPhone.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|x64.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|x86.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|Any CPU.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|ARM.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|x64.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|x86.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|ARM.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|x64.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|x86.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|Any CPU.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|ARM.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|iPhone.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|x64.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|x86.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|ARM.ActiveCfg = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|ARM.Build.0 = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|Mixed Platforms.Build.0 = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|x86.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|x86.Build.0 = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|Any CPU.Build.0 = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|ARM.ActiveCfg = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|ARM.Build.0 = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|Mixed Platforms.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|Mixed Platforms.Build.0 = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|x64.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|x86.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|x86.Build.0 = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|ARM.ActiveCfg = Debug|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|ARM.Build.0 = Debug|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|x64.ActiveCfg = Debug|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|x86.ActiveCfg = Debug|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|x86.Build.0 = Debug|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|Any CPU.Build.0 = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|ARM.ActiveCfg = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|ARM.Build.0 = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|iPhone.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|Mixed Platforms.Build.0 = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|x64.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|x86.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|x86.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|Any CPU.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|ARM.ActiveCfg = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|ARM.Build.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|ARM.Deploy.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|iPhone.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|Mixed Platforms.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|Mixed Platforms.Deploy.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|x64.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|x86.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|x86.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|x86.Deploy.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|Any CPU.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|ARM.ActiveCfg = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|ARM.Build.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|ARM.Deploy.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|iPhone.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|iPhoneSimulator.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|Mixed Platforms.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|Mixed Platforms.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|Mixed Platforms.Deploy.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|x64.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|x86.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|x86.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|x86.Deploy.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|Any CPU.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|ARM.ActiveCfg = Debug|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|ARM.Build.0 = Debug|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|ARM.Deploy.0 = Debug|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|iPhone.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|Mixed Platforms.Deploy.0 = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|x64.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|x86.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|x86.Build.0 = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|x86.Deploy.0 = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|Any CPU.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|ARM.ActiveCfg = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|ARM.Build.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|ARM.Deploy.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|iPhone.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|iPhoneSimulator.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|Mixed Platforms.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|Mixed Platforms.Deploy.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|x64.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|x86.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|x86.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|x86.Deploy.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {03799AD1-9FCF-48CB-8E6E-B233DF583B10} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0} = {0C4021EF-617B-4620-ADD3-A702B4F9FA86} + {F662E15A-8753-468E-A67E-3FCF45F12B89} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {C129735F-5D4B-40BE-9410-F43E548FFF5E} = {0C4021EF-617B-4620-ADD3-A702B4F9FA86} + {9E5D6B89-B69B-486B-9F7B-406BE8690589} = {49C7015B-F41A-47A6-8200-B925902E74E9} + {38AF8105-65B6-4A14-A258-1137D9E40EF1} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {46DF3E43-6B65-4C3D-8911-64FCC301040F} = {0C4021EF-617B-4620-ADD3-A702B4F9FA86} + EndGlobalSection +EndGlobal diff --git a/SQLite.Net.sln b/SQLite.Net.sln new file mode 100644 index 000000000..f50d364b5 --- /dev/null +++ b/SQLite.Net.sln @@ -0,0 +1,940 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +VisualStudioVersion = 12.0.30723.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{59584026-7610-4CD5-A74E-D2B0A2E1CE87}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Platform.Win32", "src\SQLite.Net.Platform.Win32\SQLite.Net.Platform.Win32.csproj", "{03799AD1-9FCF-48CB-8E6E-B233DF583B10}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Platform.WinRT", "src\SQLite.Net.Platform.WinRT\SQLite.Net.Platform.WinRT.csproj", "{6891E212-AEEE-4763-AC6F-BD7213C13890}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Platform.WindowsPhone8", "src\SQLite.Net.Platform.WindowsPhone8\SQLite.Net.Platform.WindowsPhone8.csproj", "{741521F8-F9D8-40F4-A5D4-AED4E26841ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Platform.XamarinIOS", "src\SQLite.Net.Platform.XamarinIOS\SQLite.Net.Platform.XamarinIOS.csproj", "{6377929D-6253-450D-BF4B-3E8ECE2564F7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Platform.XamarinAndroid", "src\SQLite.Net.Platform.XamarinAndroid\SQLite.Net.Platform.XamarinAndroid.csproj", "{219700F0-5444-4250-87D6-0551B39CA402}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Platform.Generic", "src\SQLite.Net.Platform.Generic\SQLite.Net.Platform.Generic.csproj", "{F662E15A-8753-468E-A67E-3FCF45F12B89}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Platform.WindowsPhoneApp81", "src\SQLite.Net.Platform.WindowsPhoneApp81\SQLite.Net.Platform.WindowsPhoneApp81.csproj", "{38AF8105-65B6-4A14-A258-1137D9E40EF1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Platform.XamarinIOS.Unified", "src\SQLite.Net.Platform.XamarinIOS.Unified\SQLite.Net.Platform.XamarinIOS.Unified.csproj", "{3173703F-8B1F-4772-9AE3-44913F413FB1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{0C4021EF-617B-4620-ADD3-A702B4F9FA86}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Tests.Win32", "tests\SQLite.Net.Tests.Win32\SQLite.Net.Tests.Win32.csproj", "{BFF4B373-2844-40AD-8994-2BA5AC42AEE0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Tests.XamarinIOS", "tests\SQLite.Net.Tests.XamarinIOS\SQLite.Net.Tests.XamarinIOS.csproj", "{4B386F57-D313-4842-AE9B-F54EDBF1EBD5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Tests.WinRT", "tests\SQLite.Net.Tests.WinRT\SQLite.Net.Tests.WinRT.csproj", "{5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Tests.XamarinAndroid", "tests\SQLite.Net.Tests.XamarinAndroid\SQLite.Net.Tests.XamarinAndroid.csproj", "{2C3224FB-4513-4A16-B67F-3C4F1BDC7765}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Tests.Generic", "tests\SQLite.Net.Tests.Generic\SQLite.Net.Tests.Generic.csproj", "{C129735F-5D4B-40BE-9410-F43E548FFF5E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Tests.WindowsPhone8", "tests\SQLite.Net.Tests.WindowsPhone8\SQLite.Net.Tests.WindowsPhone8.csproj", "{46DF3E43-6B65-4C3D-8911-64FCC301040F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Tests.XamarinIOS.Unified", "tests\SQLite.Net.Tests.XamarinIOS.Unified\SQLite.Net.Tests.XamarinIOS.Unified.csproj", "{0A947CD1-3C6F-415A-A122-233BAE3005FD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{49C7015B-F41A-47A6-8200-B925902E74E9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stocks", "examples\Stocks\Stocks.csproj", "{9E5D6B89-B69B-486B-9F7B-406BE8690589}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{5BD976ED-6E22-44A3-A5A1-D6C6633BAADD}" + ProjectSection(SolutionItems) = preProject + .nuget\NuGet.Config = .nuget\NuGet.Config + .nuget\NuGet.exe = .nuget\NuGet.exe + .nuget\NuGet.targets = .nuget\NuGet.targets + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net", "src\SQLite.Net\SQLite.Net.csproj", "{4971D437-0694-4297-A8CC-146CE08C3BD9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Net.Async", "src\SQLite.Net.Async\SQLite.Net.Async.csproj", "{3AB34E91-8E1A-442F-8E66-2494B371A890}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Ad-Hoc|Any CPU = Ad-Hoc|Any CPU + Ad-Hoc|ARM = Ad-Hoc|ARM + Ad-Hoc|iPhone = Ad-Hoc|iPhone + Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator + Ad-Hoc|Mixed Platforms = Ad-Hoc|Mixed Platforms + Ad-Hoc|x64 = Ad-Hoc|x64 + Ad-Hoc|x86 = Ad-Hoc|x86 + AppStore|Any CPU = AppStore|Any CPU + AppStore|ARM = AppStore|ARM + AppStore|iPhone = AppStore|iPhone + AppStore|iPhoneSimulator = AppStore|iPhoneSimulator + AppStore|Mixed Platforms = AppStore|Mixed Platforms + AppStore|x64 = AppStore|x64 + AppStore|x86 = AppStore|x86 + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|iPhone = Debug|iPhone + Debug|iPhoneSimulator = Debug|iPhoneSimulator + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|iPhone = Release|iPhone + Release|iPhoneSimulator = Release|iPhoneSimulator + Release|Mixed Platforms = Release|Mixed Platforms + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|Any CPU.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|ARM.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|x64.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.AppStore|x86.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|ARM.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|x64.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Debug|x86.ActiveCfg = Debug|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|Any CPU.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|ARM.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|iPhone.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|x64.ActiveCfg = Release|Any CPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10}.Release|x86.ActiveCfg = Release|Any CPU + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|ARM.ActiveCfg = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|ARM.Build.0 = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|Mixed Platforms.ActiveCfg = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|Mixed Platforms.Build.0 = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|x64.ActiveCfg = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|x64.Build.0 = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|x86.ActiveCfg = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Ad-Hoc|x86.Build.0 = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|Any CPU.Build.0 = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|ARM.ActiveCfg = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|ARM.Build.0 = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|iPhone.ActiveCfg = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|iPhone.Build.0 = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|iPhoneSimulator.Build.0 = Ad-Hoc|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|Mixed Platforms.ActiveCfg = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|Mixed Platforms.Build.0 = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|x64.ActiveCfg = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|x64.Build.0 = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|x86.ActiveCfg = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.AppStore|x86.Build.0 = AppStore|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|Any CPU.ActiveCfg = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|Any CPU.Build.0 = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|ARM.ActiveCfg = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|ARM.Build.0 = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|iPhone.ActiveCfg = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|iPhone.Build.0 = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|Mixed Platforms.ActiveCfg = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|Mixed Platforms.Build.0 = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|x64.ActiveCfg = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|x64.Build.0 = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|x86.ActiveCfg = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Debug|x86.Build.0 = Debug|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|Any CPU.ActiveCfg = Release|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|Any CPU.Build.0 = Release|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|ARM.ActiveCfg = Release|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|iPhone.ActiveCfg = Release|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|iPhone.Build.0 = Release|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|Mixed Platforms.ActiveCfg = Release|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|Mixed Platforms.Build.0 = Release|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|x64.ActiveCfg = Release|iPhone + {0A947CD1-3C6F-415A-A122-233BAE3005FD}.Release|x86.ActiveCfg = Release|iPhone + {219700F0-5444-4250-87D6-0551B39CA402}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.AppStore|Any CPU.Build.0 = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.AppStore|ARM.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.AppStore|x64.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.AppStore|x86.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Debug|Any CPU.Build.0 = Debug|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Debug|ARM.ActiveCfg = Debug|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Debug|x64.ActiveCfg = Debug|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Debug|x86.ActiveCfg = Debug|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Release|Any CPU.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Release|Any CPU.Build.0 = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Release|ARM.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Release|iPhone.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Release|x64.ActiveCfg = Release|Any CPU + {219700F0-5444-4250-87D6-0551B39CA402}.Release|x86.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|Mixed Platforms.Deploy.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|Any CPU.Build.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|Any CPU.Deploy.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|ARM.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|Mixed Platforms.Deploy.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|x64.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.AppStore|x86.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|ARM.ActiveCfg = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|x64.ActiveCfg = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Debug|x86.ActiveCfg = Debug|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|Any CPU.Build.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|Any CPU.Deploy.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|ARM.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|iPhone.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|x64.ActiveCfg = Release|Any CPU + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765}.Release|x86.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|ARM.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|x64.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Ad-Hoc|x86.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|Any CPU.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|ARM.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|ARM.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|iPhone.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|x64.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|x64.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|x86.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.AppStore|x86.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|ARM.ActiveCfg = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|ARM.Build.0 = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|iPhone.Build.0 = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|x64.ActiveCfg = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|x64.Build.0 = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|x86.ActiveCfg = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Debug|x86.Build.0 = Debug|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|Any CPU.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|ARM.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|iPhone.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|iPhone.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|x64.ActiveCfg = Release|Any CPU + {3173703F-8B1F-4772-9AE3-44913F413FB1}.Release|x86.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|ARM.ActiveCfg = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|ARM.Build.0 = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|Mixed Platforms.Build.0 = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|x86.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Ad-Hoc|x86.Build.0 = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|Any CPU.Build.0 = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|ARM.ActiveCfg = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|ARM.Build.0 = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|Mixed Platforms.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|Mixed Platforms.Build.0 = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|x64.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|x86.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.AppStore|x86.Build.0 = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|ARM.ActiveCfg = Debug|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|ARM.Build.0 = Debug|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|x64.ActiveCfg = Debug|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|x86.ActiveCfg = Debug|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Debug|x86.Build.0 = Debug|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|Any CPU.Build.0 = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|ARM.ActiveCfg = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|ARM.Build.0 = Release|ARM + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|iPhone.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|Mixed Platforms.Build.0 = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|x64.ActiveCfg = Release|Any CPU + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|x86.ActiveCfg = Release|x86 + {38AF8105-65B6-4A14-A258-1137D9E40EF1}.Release|x86.Build.0 = Release|x86 + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|Any CPU.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|ARM.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|x64.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.AppStore|x86.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|ARM.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|x64.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Debug|x86.ActiveCfg = Debug|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|Any CPU.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|ARM.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|iPhone.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|x64.ActiveCfg = Release|Any CPU + {3AB34E91-8E1A-442F-8E66-2494B371A890}.Release|x86.ActiveCfg = Release|Any CPU + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|Any CPU.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|ARM.ActiveCfg = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|ARM.Build.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|ARM.Deploy.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|iPhone.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|Mixed Platforms.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|Mixed Platforms.Deploy.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|x64.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|x86.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|x86.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Ad-Hoc|x86.Deploy.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|Any CPU.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|ARM.ActiveCfg = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|ARM.Build.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|ARM.Deploy.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|iPhone.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|iPhoneSimulator.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|Mixed Platforms.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|Mixed Platforms.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|Mixed Platforms.Deploy.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|x64.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|x86.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|x86.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.AppStore|x86.Deploy.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|Any CPU.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|ARM.ActiveCfg = Debug|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|ARM.Build.0 = Debug|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|ARM.Deploy.0 = Debug|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|iPhone.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|Mixed Platforms.Deploy.0 = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|x64.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|x86.ActiveCfg = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|x86.Build.0 = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Debug|x86.Deploy.0 = Debug|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|Any CPU.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|ARM.ActiveCfg = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|ARM.Build.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|ARM.Deploy.0 = Release|ARM + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|iPhone.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|iPhoneSimulator.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|Mixed Platforms.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|Mixed Platforms.Deploy.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|x64.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|x86.ActiveCfg = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|x86.Build.0 = Release|x86 + {46DF3E43-6B65-4C3D-8911-64FCC301040F}.Release|x86.Deploy.0 = Release|x86 + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|Any CPU.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|ARM.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|x64.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.AppStore|x86.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|ARM.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|x64.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Debug|x86.ActiveCfg = Debug|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|Any CPU.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|ARM.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|iPhone.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|x64.ActiveCfg = Release|Any CPU + {4971D437-0694-4297-A8CC-146CE08C3BD9}.Release|x86.ActiveCfg = Release|Any CPU + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|ARM.ActiveCfg = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|iPhone.Deploy.0 = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Ad-Hoc|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|Mixed Platforms.ActiveCfg = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|Mixed Platforms.Build.0 = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|Mixed Platforms.Deploy.0 = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|x64.ActiveCfg = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Ad-Hoc|x86.ActiveCfg = Ad-Hoc|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|Any CPU.Build.0 = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|ARM.ActiveCfg = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|iPhone.ActiveCfg = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|iPhone.Build.0 = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|iPhone.Deploy.0 = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|iPhoneSimulator.Deploy.0 = AppStore|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|Mixed Platforms.ActiveCfg = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|Mixed Platforms.Build.0 = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|Mixed Platforms.Deploy.0 = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|x64.ActiveCfg = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.AppStore|x86.ActiveCfg = AppStore|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|Any CPU.ActiveCfg = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|Any CPU.Build.0 = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|ARM.ActiveCfg = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|iPhone.ActiveCfg = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|iPhone.Build.0 = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|iPhone.Deploy.0 = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|iPhoneSimulator.Deploy.0 = Debug|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|Mixed Platforms.ActiveCfg = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|Mixed Platforms.Build.0 = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|Mixed Platforms.Deploy.0 = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|x64.ActiveCfg = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Debug|x86.ActiveCfg = Debug|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|Any CPU.ActiveCfg = Release|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|Any CPU.Build.0 = Release|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|ARM.ActiveCfg = Release|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|iPhone.ActiveCfg = Release|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|iPhone.Build.0 = Release|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|iPhone.Deploy.0 = Release|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|iPhoneSimulator.Deploy.0 = Release|iPhoneSimulator + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|Mixed Platforms.ActiveCfg = Release|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|Mixed Platforms.Build.0 = Release|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|Mixed Platforms.Deploy.0 = Release|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|x64.ActiveCfg = Release|iPhone + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5}.Release|x86.ActiveCfg = Release|iPhone + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|ARM.ActiveCfg = Release|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|ARM.Build.0 = Release|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|ARM.Deploy.0 = Release|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|Mixed Platforms.Build.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|Mixed Platforms.Deploy.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|x64.ActiveCfg = Release|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|x64.Build.0 = Release|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|x64.Deploy.0 = Release|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|x86.ActiveCfg = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|x86.Build.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Ad-Hoc|x86.Deploy.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|Any CPU.Build.0 = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|Any CPU.Deploy.0 = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|ARM.ActiveCfg = Release|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|ARM.Build.0 = Release|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|ARM.Deploy.0 = Release|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|Mixed Platforms.ActiveCfg = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|Mixed Platforms.Build.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|Mixed Platforms.Deploy.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|x64.ActiveCfg = Release|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|x64.Build.0 = Release|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|x64.Deploy.0 = Release|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|x86.ActiveCfg = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|x86.Build.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.AppStore|x86.Deploy.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|ARM.ActiveCfg = Debug|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|ARM.Build.0 = Debug|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|ARM.Deploy.0 = Debug|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|Mixed Platforms.Deploy.0 = Debug|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|x64.ActiveCfg = Debug|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|x64.Build.0 = Debug|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|x64.Deploy.0 = Debug|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|x86.ActiveCfg = Debug|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|x86.Build.0 = Debug|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Debug|x86.Deploy.0 = Debug|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|Any CPU.Build.0 = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|Any CPU.Deploy.0 = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|ARM.ActiveCfg = Release|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|ARM.Build.0 = Release|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|ARM.Deploy.0 = Release|ARM + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|iPhone.ActiveCfg = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|Mixed Platforms.Build.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|Mixed Platforms.Deploy.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|x64.ActiveCfg = Release|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|x64.Build.0 = Release|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|x64.Deploy.0 = Release|x64 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|x86.ActiveCfg = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|x86.Build.0 = Release|x86 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753}.Release|x86.Deploy.0 = Release|x86 + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.AppStore|Any CPU.Build.0 = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.AppStore|ARM.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.AppStore|x64.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.AppStore|x86.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Debug|ARM.ActiveCfg = Debug|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Debug|x64.ActiveCfg = Debug|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Debug|x86.ActiveCfg = Debug|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|Any CPU.Build.0 = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|ARM.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|iPhone.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|iPhone.Build.0 = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|x64.ActiveCfg = Release|Any CPU + {6377929D-6253-450D-BF4B-3E8ECE2564F7}.Release|x86.ActiveCfg = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|ARM.ActiveCfg = Release|ARM + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|ARM.Build.0 = Release|ARM + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|Mixed Platforms.Build.0 = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|x64.ActiveCfg = Release|x64 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|x64.Build.0 = Release|x64 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|x86.ActiveCfg = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Ad-Hoc|x86.Build.0 = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|Any CPU.Build.0 = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|ARM.ActiveCfg = Release|ARM + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|ARM.Build.0 = Release|ARM + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|Mixed Platforms.ActiveCfg = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|Mixed Platforms.Build.0 = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|x64.ActiveCfg = Release|x64 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|x64.Build.0 = Release|x64 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|x86.ActiveCfg = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.AppStore|x86.Build.0 = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|ARM.ActiveCfg = Debug|ARM + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|ARM.Build.0 = Debug|ARM + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|x64.ActiveCfg = Debug|x64 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|x64.Build.0 = Debug|x64 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|x86.ActiveCfg = Debug|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Debug|x86.Build.0 = Debug|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|Any CPU.Build.0 = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|ARM.ActiveCfg = Release|ARM + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|ARM.Build.0 = Release|ARM + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|iPhone.ActiveCfg = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|Mixed Platforms.Build.0 = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|x64.ActiveCfg = Release|x64 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|x64.Build.0 = Release|x64 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|x86.ActiveCfg = Release|x86 + {6891E212-AEEE-4763-AC6F-BD7213C13890}.Release|x86.Build.0 = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|ARM.ActiveCfg = Release|ARM + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|ARM.Build.0 = Release|ARM + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|Mixed Platforms.Build.0 = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|x86.ActiveCfg = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Ad-Hoc|x86.Build.0 = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|Any CPU.Build.0 = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|ARM.ActiveCfg = Release|ARM + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|ARM.Build.0 = Release|ARM + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|Mixed Platforms.ActiveCfg = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|Mixed Platforms.Build.0 = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|x64.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|x86.ActiveCfg = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.AppStore|x86.Build.0 = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|ARM.ActiveCfg = Debug|ARM + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|ARM.Build.0 = Debug|ARM + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|x64.ActiveCfg = Debug|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|x86.ActiveCfg = Debug|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Debug|x86.Build.0 = Debug|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|Any CPU.Build.0 = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|ARM.ActiveCfg = Release|ARM + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|ARM.Build.0 = Release|ARM + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|iPhone.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|Mixed Platforms.Build.0 = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|x64.ActiveCfg = Release|Any CPU + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|x86.ActiveCfg = Release|x86 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED}.Release|x86.Build.0 = Release|x86 + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|Any CPU.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|ARM.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|x64.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.AppStore|x86.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|ARM.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|x64.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|x86.ActiveCfg = Debug|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|Any CPU.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|ARM.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|iPhone.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|x64.ActiveCfg = Release|Any CPU + {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|x86.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|Any CPU.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|ARM.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|x64.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.AppStore|x86.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|ARM.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|x64.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Debug|x86.ActiveCfg = Debug|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|Any CPU.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|ARM.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|iPhone.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|x64.ActiveCfg = Release|Any CPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0}.Release|x86.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|ARM.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|x64.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Ad-Hoc|x86.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|Any CPU.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|ARM.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|ARM.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|iPhone.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|x64.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|x64.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|x86.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.AppStore|x86.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|ARM.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|iPhone.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|x64.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|x64.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|x86.ActiveCfg = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Debug|x86.Build.0 = Debug|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|Any CPU.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|ARM.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|ARM.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|iPhone.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|iPhone.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|x64.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|x64.Build.0 = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|x86.ActiveCfg = Release|Any CPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E}.Release|x86.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|ARM.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|x64.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Ad-Hoc|x86.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|Any CPU.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|ARM.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|ARM.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|iPhone.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|x64.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|x64.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|x86.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.AppStore|x86.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|ARM.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|ARM.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|iPhone.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|x64.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|x64.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|x86.ActiveCfg = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Debug|x86.Build.0 = Debug|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|Any CPU.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|ARM.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|ARM.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|iPhone.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|iPhone.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|x64.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|x64.Build.0 = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|x86.ActiveCfg = Release|Any CPU + {F662E15A-8753-468E-A67E-3FCF45F12B89}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {03799AD1-9FCF-48CB-8E6E-B233DF583B10} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {6891E212-AEEE-4763-AC6F-BD7213C13890} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {741521F8-F9D8-40F4-A5D4-AED4E26841ED} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {6377929D-6253-450D-BF4B-3E8ECE2564F7} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {219700F0-5444-4250-87D6-0551B39CA402} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {F662E15A-8753-468E-A67E-3FCF45F12B89} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {38AF8105-65B6-4A14-A258-1137D9E40EF1} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {3173703F-8B1F-4772-9AE3-44913F413FB1} = {59584026-7610-4CD5-A74E-D2B0A2E1CE87} + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0} = {0C4021EF-617B-4620-ADD3-A702B4F9FA86} + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5} = {0C4021EF-617B-4620-ADD3-A702B4F9FA86} + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753} = {0C4021EF-617B-4620-ADD3-A702B4F9FA86} + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765} = {0C4021EF-617B-4620-ADD3-A702B4F9FA86} + {C129735F-5D4B-40BE-9410-F43E548FFF5E} = {0C4021EF-617B-4620-ADD3-A702B4F9FA86} + {46DF3E43-6B65-4C3D-8911-64FCC301040F} = {0C4021EF-617B-4620-ADD3-A702B4F9FA86} + {0A947CD1-3C6F-415A-A122-233BAE3005FD} = {0C4021EF-617B-4620-ADD3-A702B4F9FA86} + {9E5D6B89-B69B-486B-9F7B-406BE8690589} = {49C7015B-F41A-47A6-8200-B925902E74E9} + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/SQLite.Net.sln.DotSettings b/SQLite.Net.sln.DotSettings new file mode 100644 index 000000000..d5bb18362 --- /dev/null +++ b/SQLite.Net.sln.DotSettings @@ -0,0 +1,20 @@ + + SOLUTION + True + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + 160 + CHOP_ALWAYS + + IO + IOS + OK + PK + RT + SQ + WP + True \ No newline at end of file diff --git a/SQLite.sln b/SQLite.sln deleted file mode 100644 index b0f6afe8e..000000000 --- a/SQLite.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Tests", "tests\SQLite.Tests.csproj", "{6947A8F1-99BE-4DD1-AD4D-D89425CE67A2}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6947A8F1-99BE-4DD1-AD4D-D89425CE67A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6947A8F1-99BE-4DD1-AD4D-D89425CE67A2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6947A8F1-99BE-4DD1-AD4D-D89425CE67A2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6947A8F1-99BE-4DD1-AD4D-D89425CE67A2}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = tests\SQLite.Tests.csproj - EndGlobalSection -EndGlobal diff --git a/examples/Stocks/Main.cs b/examples/Stocks/Main.cs index 0c9bb8bc4..55025e2da 100644 --- a/examples/Stocks/Main.cs +++ b/examples/Stocks/Main.cs @@ -3,7 +3,6 @@ using System.Linq; using Path = System.IO.Path; -using SQLite; namespace Stocks.CommandLine { @@ -56,7 +55,7 @@ void ListStocks () void DisplayBanner () { Console.WriteLine ("Stocks - a demo of sqlite-net"); - Console.WriteLine ("Using " + _db.Database); + Console.WriteLine ("Using " + _db.DatabasePath); Console.WriteLine (); } diff --git a/examples/Stocks/Stocks.cs b/examples/Stocks/Stocks.cs index fba9a798b..cac8cc177 100644 --- a/examples/Stocks/Stocks.cs +++ b/examples/Stocks/Stocks.cs @@ -1,6 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; +using SQLite.Net; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; +using SQLite.Net.Platform.Win32; using Path = System.IO.Path; using SQLite; @@ -38,7 +42,7 @@ public override string ToString () public class Database : SQLiteConnection { - public Database (string path) : base(path) + public Database (string path) : base(new SQLitePlatformWin32(), path) { CreateTable (); CreateTable (); diff --git a/examples/Stocks/Stocks.csproj b/examples/Stocks/Stocks.csproj index 2d6fa2631..c8ab0eda8 100644 --- a/examples/Stocks/Stocks.csproj +++ b/examples/Stocks/Stocks.csproj @@ -1,15 +1,34 @@ - - + + Debug AnyCPU - 9.0.21022 - 2.0 {9E5D6B89-B69B-486B-9F7B-406BE8690589} Exe Stocks Stocks - v3.5 + v4.5 + + + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true true @@ -19,6 +38,7 @@ DEBUG prompt 4 + false none @@ -26,18 +46,41 @@ bin\Release prompt 4 + false - - 3.5 - + - + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + + + {03799AD1-9FCF-48CB-8E6E-B233DF583B10} + SQLite.Net.Platform.Win32 + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + \ No newline at end of file diff --git a/examples/Stocks/app.config b/examples/Stocks/app.config new file mode 100644 index 000000000..e36560333 --- /dev/null +++ b/examples/Stocks/app.config @@ -0,0 +1,3 @@ + + + diff --git a/examples/StocksImplicit/Main.cs b/examples/StocksImplicit/Main.cs deleted file mode 100644 index 73ff37267..000000000 --- a/examples/StocksImplicit/Main.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Path = System.IO.Path; - -using SQLite; - -namespace Stocks.CommandLine -{ - class Program - { - public static void Main (string[] args) - { - new Program ().Run (); - } - - Database _db; - - void Initialize () - { - var dbPath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "StocksImplicit.db"); - _db = new Database (dbPath); - } - - void DisplayStock (string stockSymbol) - { - var stock = _db.QueryStock (stockSymbol); - - if (stock == null) { - Console.WriteLine ("I don't know about {0}", stockSymbol); - Console.WriteLine ("Run \"up {0}\" to update the stock", stockSymbol); - } else { - - // - // Display the last 1 week - // - foreach (var v in _db.QueryValuations (stock)) { - Console.WriteLine (" {0}", v); - } - - } - } - - void UpdateStock (string stockSymbol) - { - _db.UpdateStock(stockSymbol); - } - - void ListStocks () - { - foreach (var stock in _db.QueryAllStocks ()) { - Console.WriteLine (stock); - } - } - - void DisplayBanner () - { - Console.WriteLine ("Stocks - a demo of sqlite-net"); - Console.WriteLine ("Using " + _db.DatabaseName); - Console.WriteLine (); - } - - void DisplayHelp (string cmd) - { - Action display = (c, h) => { Console.WriteLine ("{0} {1}", c, h); }; - var cmds = new SortedDictionary { - { - "ls", - "\t List all known stocks" - }, - { - "exit", - "\t Exit stocks" - }, - { - "up stock", - "Updates stock" - }, - { - "help", - "\t Displays help" - }, - { - "stock", - "\t Displays latest valuations for stock" - } - }; - if (cmds.ContainsKey (cmd)) { - display (cmd, cmds[cmd]); - } else { - foreach (var ch in cmds) { - display (ch.Key, ch.Value); - } - } - } - - void Run () - { - var WS = new char[] { - ' ', - '\t', - '\r', - '\n' - }; - - Initialize (); - - DisplayBanner (); - DisplayHelp (""); - - for (;;) { - Console.Write ("$ "); - var cmdline = Console.ReadLine (); - - var args = cmdline.Split (WS, StringSplitOptions.RemoveEmptyEntries); - if (args.Length < 1) - continue; - var cmd = args[0].ToLowerInvariant (); - - if (cmd == "?" || cmd == "help") { - DisplayHelp (""); - } else if (cmd == "exit") { - break; - } else if (cmd == "ls") { - ListStocks (); - } else if (cmd == "up") { - if (args.Length == 2) { - UpdateStock (args[1].ToUpperInvariant ()); - } else { - DisplayHelp ("up stock"); - } - } else { - DisplayStock (cmd.ToUpperInvariant ()); - } - } - } - } -} diff --git a/examples/StocksImplicit/Stocks.cs b/examples/StocksImplicit/Stocks.cs deleted file mode 100644 index cba31d14e..000000000 --- a/examples/StocksImplicit/Stocks.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Path = System.IO.Path; - -using SQLite; -using System.Globalization; - -namespace Stocks -{ - public class Stock - { - public Guid Id { get; set; } - public string Symbol { get; set; } - - public override string ToString () - { - return Symbol; - } - } - - public class Valuation - { - public Guid Id { get; set; } - public Guid StockId { get; set; } - public DateTime Time { get; set; } - public decimal Price { get; set; } - - public override string ToString () - { - return string.Format ("{0:MMM dd yy} {1:C}", Time, Price); - } - } - - public class Database : SQLiteConnection - { - public Database (string path) : base(path) - { - CreateTable(CreateFlags.AllImplicit | CreateFlags.AutoIncPK); - CreateTable(CreateFlags.AllImplicit | CreateFlags.AutoIncPK); - _DatabaseName = path; - } - - private string _DatabaseName; - public string DatabaseName - { - get { return _DatabaseName; } - } - - public IEnumerable QueryValuations (Stock stock) - { - return Table ().Where(x => x.StockId == stock.Id); - } - - public Valuation QueryLatestValuation (Stock stock) - { - return Table ().Where(x => x.StockId == stock.Id).OrderByDescending(x => x.Time).Take(1).FirstOrDefault(); - } - public Stock QueryStock (string stockSymbol) - { - return (from s in Table () - where s.Symbol == stockSymbol - select s).FirstOrDefault (); - } - public IEnumerable QueryAllStocks () - { - return from s in Table () - orderby s.Symbol - select s; - } - - public void UpdateStock (string stockSymbol) - { - // - // Ensure that there is a valid Stock in the DB - // - var stock = QueryStock (stockSymbol); - if (stock == null) { - stock = new Stock { Symbol = stockSymbol }; - Insert (stock); - } - - // - // When was it last valued? - // - var latest = QueryLatestValuation (stock); - var latestDate = latest != null ? latest.Time : new DateTime (1950, 1, 1); - - // - // Get the latest valuations - // - try { - var newVals = new YahooScraper ().GetValuations (stock, latestDate + TimeSpan.FromHours (23), DateTime.Now); - InsertAll (newVals); - } catch (System.Net.WebException ex) { - Console.WriteLine (ex); - } - } - } - - public class YahooScraper - { - public IEnumerable GetValuations (Stock stock, DateTime start, DateTime end) - { - var t = "http://ichart.finance.yahoo.com/table.csv?s={0}&d={1}&e={2}&f={3}&g=d&a={4}&b={5}&c={6}&ignore=.csv"; - var url = string.Format (t, stock.Symbol, end.Month - 1, end.Day, end.Year, start.Month - 1, start.Day, start.Year); - Console.WriteLine ("GET {0}", url); - var req = System.Net.WebRequest.Create (url); - using (var resp = new System.IO.StreamReader (req.GetResponse ().GetResponseStream ())) { - var first = true; - var dateCol = 0; - var priceCol = 6; - for (var line = resp.ReadLine (); line != null; line = resp.ReadLine ()) { - var parts = line.Split (','); - if (first) { - dateCol = Array.IndexOf (parts, "Date"); - priceCol = Array.IndexOf (parts, "Adj Close"); - first = false; - } else { - yield return new Valuation { - StockId = stock.Id, - Price = decimal.Parse (parts[priceCol], CultureInfo.InvariantCulture), - Time = DateTime.Parse (parts[dateCol]) - }; - } - } - } - } - } -} diff --git a/examples/StocksImplicit/StocksImplicit.csproj b/examples/StocksImplicit/StocksImplicit.csproj deleted file mode 100644 index 8c6de88ba..000000000 --- a/examples/StocksImplicit/StocksImplicit.csproj +++ /dev/null @@ -1,77 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {9E5D6B89-B69B-486B-9F7B-406BE8690589} - Exe - Stocks - Stocks - v3.5 - - - - - 3.5 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - true - full - false - bin\Debug - DEBUG - prompt - 4 - x86 - - - none - false - bin\Release - prompt - 4 - - - - - 3.5 - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - - - \ No newline at end of file diff --git a/examples/StocksImplicit/StocksImplicit.sln b/examples/StocksImplicit/StocksImplicit.sln deleted file mode 100644 index 93706e8ac..000000000 --- a/examples/StocksImplicit/StocksImplicit.sln +++ /dev/null @@ -1,23 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StocksImplicit", "StocksImplicit.csproj", "{9E5D6B89-B69B-486B-9F7B-406BE8690589}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E5D6B89-B69B-486B-9F7B-406BE8690589}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = Stocks.csproj - EndGlobalSection -EndGlobal diff --git a/license.md b/license.md index 3a18c40ee..3c947ebf5 100644 --- a/license.md +++ b/license.md @@ -2,6 +2,7 @@ License === Copyright (c) 2009-2012 Krueger Systems, Inc. +Copyright (c) 2013 Øystein Krog Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/nuget/NuGet.exe b/nuget/NuGet.exe deleted file mode 100644 index 79482f60d..000000000 Binary files a/nuget/NuGet.exe and /dev/null differ diff --git a/nuget/SQLite.Net.Async.nuspec b/nuget/SQLite.Net.Async.nuspec new file mode 100644 index 000000000..8637f18b5 --- /dev/null +++ b/nuget/SQLite.Net.Async.nuspec @@ -0,0 +1,26 @@ + + + + SQLite.Net.Async-PCL + 2.5 + SQLite.Net.Async PCL + Øystein Krog,Frank Krueger,Tim Heuer + Øystein Krog + https://raw.github.com/oysteinkrog/SQLite.Net-PCL/master/LICENSE.txt + https://github.com/oysteinkrog/SQLite.Net-PCL + false + SQLite.Net PCL is an open source, minimal library to allow .NET and Mono applications to store data in SQLite databases. +This is a fork of the original sqlite-net project, which aims to cleanup/improve the code and deliver the package as PCL assemblies with some additional platform-specific implementations. +This package is compatible with the following .net platforms: net4+sl5+wp8+win8+monotouch+monoAndroid + A .NET client library to access SQLite embedded database files in a LINQ manner. +This package provides Async extensions to the core SQLite.Net package. + https://github.com/oysteinkrog/SQLite.Net-PCL/commits + sqlite pcl sql database async monotouch ios monodroid android win32 metro winrt + + + + + + + + diff --git a/nuget/SQLite.Net.Platform.Generic.nuspec b/nuget/SQLite.Net.Platform.Generic.nuspec new file mode 100644 index 000000000..1e0a657e3 --- /dev/null +++ b/nuget/SQLite.Net.Platform.Generic.nuspec @@ -0,0 +1,23 @@ + + + + SQLite.Net.Platform.Generic + 2.5 + SQLite.Net PCL - Generic Platform + Øystein Krog,Frank Krueger,Tim Heuer,James Ottaway + Øystein Krog + https://raw.github.com/oysteinkrog/SQLite.Net-PCL/master/LICENSE.txt + https://github.com/oysteinkrog/SQLite.Net-PCL + false + SQLite.Net PCL is an open source, minimal library to allow .NET and Mono applications to store data in SQLite databases. It is written in C# 3.0 and is meant to be simply compiled in with your projects. It was first designed to work with MonoTouch on the iPhone, but should work in any other CLI environment. + A .NET client library to access SQLite embedded database files in a LINQ manner. + https://github.com/oysteinkrog/SQLite.Net-PCL/commits + sqlite pcl sql database + + + + + + + + diff --git a/nuget/SQLite.Net.Platform.Win32.nuspec b/nuget/SQLite.Net.Platform.Win32.nuspec new file mode 100644 index 000000000..59eaf8bbd --- /dev/null +++ b/nuget/SQLite.Net.Platform.Win32.nuspec @@ -0,0 +1,24 @@ + + + + SQLite.Net.Platform.Win32 + 2.5 + SQLite.Net PCL - Win32 Platform + Øystein Krog,Frank Krueger,Tim Heuer + Øystein Krog + https://raw.github.com/oysteinkrog/SQLite.Net-PCL/master/LICENSE.txt + https://github.com/oysteinkrog/SQLite.Net-PCL + false + SQLite.Net PCL is an open source, minimal library to allow .NET and Mono applications to store data in SQLite databases. It is written in C# 3.0 and is meant to be simply compiled in with your projects. It was first designed to work with MonoTouch on the iPhone, but should work in any other CLI environment. + A .NET client library to access SQLite embedded database files in a LINQ manner. + https://github.com/oysteinkrog/SQLite.Net-PCL/commits + sqlite pcl sql win32 database + + + + + + + + + diff --git a/nuget/SQLite.Net.Platform.WinRT.nuspec b/nuget/SQLite.Net.Platform.WinRT.nuspec new file mode 100644 index 000000000..36dcde6bd --- /dev/null +++ b/nuget/SQLite.Net.Platform.WinRT.nuspec @@ -0,0 +1,24 @@ + + + + SQLite.Net.Platform.WinRT + 2.5 + SQLite.Net PCL - WinRT Platform + Micah Lewis,Øystein Krog,Frank Krueger,Tim Heuer,Nick Cipollina + Micah Lewis,Øystein Krog + https://raw.github.com/oysteinkrog/SQLite.Net-PCL/master/LICENSE.txt + https://github.com/oysteinkrog/SQLite.Net-PCL + false + SQLite.Net PCL is an open source, minimal library to allow .NET and Mono applications to store data in SQLite databases. This is a fork of the original sqlite-net project, which aims to cleanup/improve the code and deliver the package as PCL assemblies with some additional platform-specific implementations. To use this package you will need to install one of the platform packages or write your own implementation of ISQLitePlatform. This package is compatible with the following .net platforms: net4+sl4+wp7+win8+monotouch+MonoAndroid + A .NET client library to access SQLite embedded database files in a LINQ manner. + https://github.com/oysteinkrog/SQLite.Net-PCL/commits + sqlite pcl sql winrt database + + + + + + + + + diff --git a/nuget/SQLite.Net.Platform.WindowsPhone8.nuspec b/nuget/SQLite.Net.Platform.WindowsPhone8.nuspec new file mode 100644 index 000000000..804dde475 --- /dev/null +++ b/nuget/SQLite.Net.Platform.WindowsPhone8.nuspec @@ -0,0 +1,25 @@ + + + + SQLite.Net.Platform.WindowsPhone8 + 2.5 + SQLite.Net PCL - WindowsPhone8 Platform + Øystein Krog, Frank Krueger, Tim Heuer, Nick Cipollina + Øystein Krog + https://raw.github.com/oysteinkrog/SQLite.Net-PCL/master/LICENSE.txt + https://github.com/oysteinkrog/SQLite.Net-PCL + false + SQLite.Net PCL is an open source, minimal library to allow .NET and Mono applications to store data in SQLite databases. It is written in C# 3.0 and is meant to be simply compiled in with your projects. It was first designed to work with MonoTouch on the iPhone, but should work in any other CLI environment. + A .NET client library to access SQLite embedded database files in a LINQ manner. + https://github.com/oysteinkrog/SQLite.Net-PCL/commits + sqlite pcl sql database wp8 windows phone WindowsPhone8 + + + + + + + + + + diff --git a/nuget/SQLite.Net.Platform.XamarinAndroid.nuspec b/nuget/SQLite.Net.Platform.XamarinAndroid.nuspec new file mode 100644 index 000000000..e6c41424e --- /dev/null +++ b/nuget/SQLite.Net.Platform.XamarinAndroid.nuspec @@ -0,0 +1,23 @@ + + + + SQLite.Net.Platform.XamarinAndroid + 2.5 + SQLite.Net PCL - XamarinAndroid Platform + Øystein Krog,Frank Krueger,Tim Heuer + Øystein Krog + https://raw.github.com/oysteinkrog/SQLite.Net-PCL/master/LICENSE.txt + https://github.com/oysteinkrog/SQLite.Net-PCL + false + SQLite.Net PCL is an open source, minimal library to allow .NET and Mono applications to store data in SQLite databases. It is written in C# 3.0 and is meant to be simply compiled in with your projects. It was first designed to work with MonoTouch on the iPhone, but should work in any other CLI environment. + A .NET client library to access SQLite embedded database files in a LINQ manner. + https://github.com/oysteinkrog/SQLite.Net-PCL/commits + sqlite pcl sql database monodroid xamarin android + + + + + + + + diff --git a/nuget/SQLite.Net.Platform.XamarinIOS.nuspec b/nuget/SQLite.Net.Platform.XamarinIOS.nuspec new file mode 100644 index 000000000..525aba79e --- /dev/null +++ b/nuget/SQLite.Net.Platform.XamarinIOS.nuspec @@ -0,0 +1,24 @@ + + + + SQLite.Net.Platform.XamarinIOS + 2.5 + SQLite.Net PCL - XamarinIOS Platform + Øystein Krog,Frank Krueger,Tim Heuer + Øystein Krog + https://raw.github.com/oysteinkrog/SQLite.Net-PCL/master/LICENSE.txt + https://github.com/oysteinkrog/SQLite.Net-PCL + false + SQLite.Net PCL is an open source, minimal library to allow .NET and Mono applications to store data in SQLite databases. It is written in C# 3.0 and is meant to be simply compiled in with your projects. It was first designed to work with MonoTouch on the iPhone, but should work in any other CLI environment. + A .NET client library to access SQLite embedded database files in a LINQ manner. + https://github.com/oysteinkrog/SQLite.Net-PCL/commits + sqlite pcl sql database monotouch xamarin ios touch + + + + + + + + + diff --git a/nuget/SQLite.Net.nuspec b/nuget/SQLite.Net.nuspec new file mode 100644 index 000000000..9e7249029 --- /dev/null +++ b/nuget/SQLite.Net.nuspec @@ -0,0 +1,23 @@ + + + + SQLite.Net-PCL + 2.5 + SQLite.Net PCL + Øystein Krog,Frank Krueger,Tim Heuer + Øystein Krog + https://raw.github.com/oysteinkrog/SQLite.Net-PCL/master/LICENSE.txt + https://github.com/oysteinkrog/SQLite.Net-PCL + false + SQLite.Net PCL is an open source, minimal library to allow .NET and Mono applications to store data in SQLite databases. +This is a fork of the original sqlite-net project, which aims to cleanup/improve the code and deliver the package as PCL assemblies with some additional platform-specific implementations. +To use this package you will need to install one of the platform packages or write your own implementation of ISQLitePlatform. +This package is compatible with the following .net platforms: net4+sl4+wp7+win8+monotouch+MonoAndroid + A .NET client library to access SQLite embedded database files in a LINQ manner. + https://github.com/oysteinkrog/SQLite.Net-PCL/commits + sqlite pcl sql database monotouch ios monodroid android win32 metro winrt + + + + + diff --git a/nuget/build.bat b/nuget/build.bat index 086658e0b..0e8194172 100644 --- a/nuget/build.bat +++ b/nuget/build.bat @@ -1 +1,9 @@ -nuget pack sqlite-net.nuspec -o .\ \ No newline at end of file +@mkdir output +..\.nuget\nuget pack SQLite.Net.nuspec -o output +..\.nuget\nuget pack SQLite.Net.Async.nuspec -o output +..\.nuget\nuget pack SQLite.Net.Platform.Generic.nuspec -o output +..\.nuget\nuget pack SQLite.Net.Platform.WindowsPhone8.nuspec -o output +..\.nuget\nuget pack SQLite.Net.Platform.Win32.nuspec -o output +..\.nuget\nuget pack SQLite.Net.Platform.WinRT.nuspec -o output +..\.nuget\nuget pack SQLite.Net.Platform.XamarinAndroid.nuspec -o output +..\.nuget\nuget pack SQLite.Net.Platform.XamarinIOS.nuspec -o output diff --git a/nuget/prepare.bat b/nuget/prepare.bat new file mode 100644 index 000000000..4984e71ee --- /dev/null +++ b/nuget/prepare.bat @@ -0,0 +1,29 @@ +mkdir SQLite.Net +copy ..\src\SQLite.Net\bin\Release\SQLite.Net.dll SQLite.Net + +mkdir SQLite.Net.Async +copy ..\src\SQLite.Net.Async\bin\Release\SQLite.Net.Async.dll SQLite.Net.Async + +mkdir SQLite.Net.Platform.Generic +copy ..\src\SQLite.Net.Platform.Generic\bin\Release\SQLite.Net.Platform.Generic.dll SQLite.Net.Platform.Generic + +mkdir SQLite.Net.Platform.Win32 +copy ..\src\SQLite.Net.Platform.Win32\bin\Release\SQLite.Net.Platform.Win32.dll SQLite.Net.Platform.Win32 + +mkdir SQLite.Net.Platform.WindowsPhone8 +mkdir SQLite.Net.Platform.WindowsPhone8\ARM +mkdir SQLite.Net.Platform.WindowsPhone8\x86 +copy ..\src\SQLite.Net.Platform.WindowsPhone8\bin\x86\Release\SQLite.Net.Platform.WindowsPhone8.dll SQLite.Net.Platform.WindowsPhone8\x86 +copy ..\src\SQLite.Net.Platform.WindowsPhone8\bin\ARM\Release\SQLite.Net.Platform.WindowsPhone8.dll SQLite.Net.Platform.WindowsPhone8\ARM + +mkdir SQLite.Net.Platform.WinRT +copy ..\src\SQLite.Net.Platform.WinRT\bin\Release\SQLite.Net.Platform.WinRT.dll SQLite.Net.Platform.WinRT + +mkdir SQLite.Net.Platform.XamarinAndroid +copy ..\src\SQLite.Net.Platform.XamarinAndroid\bin\Release\SQLite.Net.Platform.XamarinAndroid.dll SQLite.Net.Platform.XamarinAndroid + +mkdir SQLite.Net.Platform.XamarinIOS +copy ..\src\SQLite.Net.Platform.XamarinIOS\bin\iPhone\Release\SQLite.Net.Platform.XamarinIOS.dll SQLite.Net.Platform.XamarinIOS + +mkdir SQLite.Net.Platform.XamarinIOS.Unified +copy ..\src\SQLite.Net.Platform.XamarinIOS.Unified\bin\Release\SQLite.Net.Platform.XamarinIOS.Unified.dll SQLite.Net.Platform.XamarinIOS.Unified diff --git a/nuget/sqlite-net.nuspec b/nuget/sqlite-net.nuspec deleted file mode 100644 index 40b6ce050..000000000 --- a/nuget/sqlite-net.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - 1.0.7 - Frank Krueger - Frank Krueger,Tim Heuer - https://github.com/praeclarum/sqlite-net - sqlite-net - sqlite-net - https://github.com/praeclarum/sqlite-net/blob/master/license.md - false - sqlite-net is an open source, minimal library to allow .NET and Mono applications to store data in SQLite databases. It is written in C# 3.0 and is meant to be simply compiled in with your projects. It was first designed to work with MonoTouch on the iPhone, but should work in any other CLI environment. - sqlite sql monotouch database metro winrt - A .NET client library to access SQLite embedded database files in a LINQ manner. - - - - - - - - - \ No newline at end of file diff --git a/nuget/upload.bat b/nuget/upload.bat new file mode 100644 index 000000000..d1c480327 --- /dev/null +++ b/nuget/upload.bat @@ -0,0 +1,8 @@ +..\.nuget\nuget push output\SQLite.Net-PCL.2.5.nupkg +..\.nuget\nuget push output\SQLite.Net.Async-PCL.2.5.nupkg +..\.nuget\nuget push output\SQLite.Net.Platform.Generic.2.5.nupkg +..\.nuget\nuget push output\SQLite.Net.Platform.WindowsPhone8.2.5.nupkg +..\.nuget\nuget push output\SQLite.Net.Platform.Win32.2.5.nupkg +..\.nuget\nuget push output\SQLite.Net.Platform.WinRT.2.5.nupkg +..\.nuget\nuget push output\SQLite.Net.Platform.XamarinAndroid.2.5.nupkg +..\.nuget\nuget push output\SQLite.Net.Platform.XamarinIOS.2.5.nupkg diff --git a/src/GlobalAssemblyInfo.cs b/src/GlobalAssemblyInfo.cs new file mode 100644 index 000000000..8f418c0bf --- /dev/null +++ b/src/GlobalAssemblyInfo.cs @@ -0,0 +1,15 @@ +using System.Reflection; + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] + +[assembly: AssemblyVersion("2.5.0.0")] +[assembly: AssemblyFileVersion("2.5.0.0")] diff --git a/src/SQLite.MonoTouchAdmin.cs b/src/SQLite.MonoTouchAdmin.cs deleted file mode 100644 index 5eabbd843..000000000 --- a/src/SQLite.MonoTouchAdmin.cs +++ /dev/null @@ -1,214 +0,0 @@ -// -// Copyright (c) 2009-2010 Krueger Systems, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -using System; -using System.Collections.Generic; -using System.Linq; -using MonoTouch.Foundation; -using MonoTouch.UIKit; -using System.Drawing; - - -namespace SQLite.MonoTouchAdmin -{ - - public class SQLiteAdmin - { - public SQLiteConnection Connection { get; private set; } - - public SQLiteAdmin (SQLiteConnection connection) - { - if (connection == null) - throw new ArgumentNullException ("connection"); - Connection = connection; - } - - public UIViewController NewTablesViewController () - { - var c = new TablesViewController (Connection); - return c; - } - - public static RectangleF GetTableRect() { - return new RectangleF (0, 0, 320, 416); - } - } - - public class TablesViewController : UIViewController - { - public SQLiteConnection Connection { get; private set; } - - public TableMapping[] TableMappings { get; private set; } - public UITableView UITable { get; private set; } - - public Data DataSource { get; private set; } - - public TablesViewController (SQLiteConnection connection) - { - if (connection == null) - throw new ArgumentNullException ("connection"); - Connection = connection; - - TableMappings = Connection.TableMappings.ToArray (); - - UITable = new UITableView (SQLiteAdmin.GetTableRect(), UITableViewStyle.Plain); - DataSource = new Data (this); - UITable.DataSource = DataSource; - UITable.Delegate = new Del (this); - } - - public override void ViewDidLoad () - { - View.AddSubview (UITable); - if (NavigationItem != null) { - NavigationItem.Title = Connection.GetType().Name; - } - } - - public class Del : UITableViewDelegate - { - TablesViewController _c; - public Del (TablesViewController c) - { - _c = c; - } - public override void RowSelected (UITableView tableView, NSIndexPath indexPath) - { - var table = _c.DataSource.GetValue(indexPath); - if (_c.NavigationController != null) { - var c = new TableViewController(table, _c.Connection); - _c.NavigationController.PushViewController(c, true); - } - } - } - - public class Data : UITableViewDataSource - { - TablesViewController _c; - public Data (TablesViewController c) - { - _c = c; - } - public override int NumberOfSections (UITableView tableView) - { - return 1; - } - public override int RowsInSection (UITableView tableview, int section) - { - return _c.TableMappings.Length; - } - public TableMapping GetValue (NSIndexPath indexPath) { - return _c.TableMappings[indexPath.Row]; - } - public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath) - { - var cell = tableView.DequeueReusableCell ("table"); - if (cell == null) { - cell = new UITableViewCell (UITableViewCellStyle.Default, "table"); - } - var table = GetValue(indexPath); - cell.TextLabel.Text = table.TableName; - return cell; - } - } - } - - public class TableViewController : UIViewController - { - public SQLiteConnection Connection { get; private set; } - - public TableMapping Table { get; private set; } - public List Rows { get; private set; } - public UITableView UITable { get; private set; } - - int PageSize = 100; - - public TableViewController (TableMapping table, SQLiteConnection connection) - { - if (table == null) - throw new ArgumentNullException ("table"); - if (connection == null) - throw new ArgumentNullException ("connection"); - Table = table; - Connection = connection; - - Rows = new List(); - - UITable = new UITableView (SQLiteAdmin.GetTableRect(), UITableViewStyle.Plain); - UITable.DataSource = new Data (this); - - GetMoreData(); - UITable.ReloadData(); - } - - void GetMoreData() { - var pk = Table.PK; - if (pk == null) { - Rows.AddRange(Connection.Query(Table, - "select * from \"" + Table.TableName + "\"")); - } - else { - var lastId = Rows.Count > 0 ? pk.GetValue(Rows[Rows.Count-1]) : 0; - Rows.AddRange(Connection.Query(Table, - "select * from \"" + Table.TableName + "\"" + - " where \"" + pk.Name + "\" > ? " + - " order by \"" + pk.Name + "\"" + - " limit " + PageSize, lastId)); - } - } - - public override void ViewDidLoad () - { - if (NavigationItem != null) { - NavigationItem.Title = Table.TableName; - } - View.AddSubview(UITable); - } - - public class Data : UITableViewDataSource { - TableViewController _c; - public Data (TableViewController c) - { - _c = c; - } - public override int NumberOfSections (UITableView tableView) - { - return 1; - } - public override int RowsInSection (UITableView tableview, int section) - { - return _c.Rows.Count; - } - public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath) - { - var cell = tableView.DequeueReusableCell ("row"); - if (cell == null) { - cell = new UITableViewCell (UITableViewCellStyle.Default, "row"); - } - var row = _c.Rows[indexPath.Row]; - cell.TextLabel.Text = row.ToString(); - return cell; - } - } - } - -} diff --git a/src/SQLite.Net.Async/AsyncTableQuery.cs b/src/SQLite.Net.Async/AsyncTableQuery.cs new file mode 100755 index 000000000..242065b82 --- /dev/null +++ b/src/SQLite.Net.Async/AsyncTableQuery.cs @@ -0,0 +1,172 @@ +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; + +namespace SQLite.Net.Async +{ + public class AsyncTableQuery + where T : new() + { + private readonly TableQuery _innerQuery; + private readonly TaskScheduler _taskScheduler; + private readonly TaskCreationOptions _taskCreationOptions = TaskCreationOptions.None; + + /// + /// + /// + /// + /// If null this parameter will be TaskScheduler.Default (evaluated when used in each method, not in ctor) + /// Defaults to DenyChildAttach + public AsyncTableQuery(TableQuery innerQuery, TaskScheduler taskScheduler = null, TaskCreationOptions taskCreationOptions = TaskCreationOptions.None) + { + if (innerQuery == null) + { + throw new ArgumentNullException("innerQuery"); + } + _innerQuery = innerQuery; + _taskScheduler = taskScheduler; + _taskCreationOptions = taskCreationOptions; + } + + public AsyncTableQuery Where(Expression> predExpr) + { + if (predExpr == null) + { + throw new ArgumentNullException("predExpr"); + } + return new AsyncTableQuery(_innerQuery.Where(predExpr), _taskScheduler ?? TaskScheduler.Default, _taskCreationOptions); + } + + public AsyncTableQuery Skip(int n) + { + return new AsyncTableQuery(_innerQuery.Skip(n), _taskScheduler ?? TaskScheduler.Default, _taskCreationOptions); + } + + public AsyncTableQuery Take(int n) + { + return new AsyncTableQuery(_innerQuery.Take(n), _taskScheduler ?? TaskScheduler.Default, _taskCreationOptions); + } + + public AsyncTableQuery OrderBy(Expression> orderExpr) + { + if (orderExpr == null) + { + throw new ArgumentNullException("orderExpr"); + } + return new AsyncTableQuery(_innerQuery.OrderBy(orderExpr), _taskScheduler ?? TaskScheduler.Default, _taskCreationOptions); + } + + public AsyncTableQuery OrderByDescending(Expression> orderExpr) + { + if (orderExpr == null) + { + throw new ArgumentNullException("orderExpr"); + } + return new AsyncTableQuery(_innerQuery.OrderByDescending(orderExpr), _taskScheduler ?? TaskScheduler.Default, _taskCreationOptions); + } + + public AsyncTableQuery ThenBy(Expression> orderExpr) + { + if (orderExpr == null) + { + throw new ArgumentNullException("orderExpr"); + } + return new AsyncTableQuery(_innerQuery.ThenBy(orderExpr), _taskScheduler ?? TaskScheduler.Default, _taskCreationOptions); + } + + public AsyncTableQuery ThenByDescending(Expression> orderExpr) + { + if (orderExpr == null) + { + throw new ArgumentNullException("orderExpr"); + } + return new AsyncTableQuery(_innerQuery.ThenByDescending(orderExpr), _taskScheduler ?? TaskScheduler.Default, _taskCreationOptions); + } + + + public Task> ToListAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock()) + { + return _innerQuery.ToList(); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task CountAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock()) + { + return _innerQuery.Count(); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task ElementAtAsync(int index, CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock()) + { + return _innerQuery.ElementAt(index); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task FirstAsync(CancellationToken cancellationToken = default (CancellationToken)) + { + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + using (((SQLiteConnectionWithLock) _innerQuery.Connection).Lock()) + { + cancellationToken.ThrowIfCancellationRequested(); + return _innerQuery.First(); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task FirstOrDefaultAsync(CancellationToken cancellationToken = default (CancellationToken)) + { + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock()) + { + cancellationToken.ThrowIfCancellationRequested(); + return _innerQuery.FirstOrDefault(); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Async/Properties/AssemblyInfo.cs b/src/SQLite.Net.Async/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..0b8b9b8bd --- /dev/null +++ b/src/SQLite.Net.Async/Properties/AssemblyInfo.cs @@ -0,0 +1,14 @@ +using System.Reflection; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("SQLite.Net.Async")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Øystein Krog")] +[assembly: AssemblyProduct("SQLite.Net.Async")] +[assembly: AssemblyCopyright("Copyright © Øystein Krog, Krueger Systems Inc.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/SQLite.Net.Async/SQLite.Net.Async.csproj b/src/SQLite.Net.Async/SQLite.Net.Async.csproj new file mode 100644 index 000000000..d281ace58 --- /dev/null +++ b/src/SQLite.Net.Async/SQLite.Net.Async.csproj @@ -0,0 +1,70 @@ + + + + + Debug + AnyCPU + {3AB34E91-8E1A-442F-8E66-2494B371A890} + Library + Properties + SQLite.Net.Async + SQLite.Net.Async + v4.5 + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Profile259 + 10.0 + ..\..\ + true + + + + + 4.0 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + + + + \ No newline at end of file diff --git a/src/SQLite.Net.Async/SQLiteAsyncConnection.cs b/src/SQLite.Net.Async/SQLiteAsyncConnection.cs new file mode 100755 index 000000000..bb15e2578 --- /dev/null +++ b/src/SQLite.Net.Async/SQLiteAsyncConnection.cs @@ -0,0 +1,511 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; + +namespace SQLite.Net.Async +{ + public class SQLiteAsyncConnection + { + private readonly Func _sqliteConnectionFunc; + private readonly TaskScheduler _taskScheduler; + private readonly TaskCreationOptions _taskCreationOptions = TaskCreationOptions.None; + + /// + /// Create a new async connection + /// + /// + /// If null this parameter will be TaskScheduler.Default (evaluated when used in each method, not in ctor) + /// Defaults to DenyChildAttach + public SQLiteAsyncConnection(Func sqliteConnectionFunc, TaskScheduler taskScheduler = null, TaskCreationOptions taskCreationOptions = TaskCreationOptions.None) + { + _sqliteConnectionFunc = sqliteConnectionFunc; + _taskCreationOptions = taskCreationOptions; + _taskScheduler = taskScheduler; + } + + protected SQLiteConnectionWithLock GetConnection() + { + return _sqliteConnectionFunc(); + } + + public Task CreateTableAsync(CancellationToken cancellationToken = default (CancellationToken)) + where T : new() + { + return CreateTablesAsync(cancellationToken, typeof(T)); + } + + public Task CreateTablesAsync(CancellationToken cancellationToken = default (CancellationToken)) + where T : new() + where T2 : new() + { + return CreateTablesAsync(cancellationToken, typeof(T), typeof(T2)); + } + + public Task CreateTablesAsync(CancellationToken cancellationToken = default (CancellationToken)) + where T : new() + where T2 : new() + where T3 : new() + { + return CreateTablesAsync(cancellationToken, typeof(T), typeof(T2), typeof(T3)); + } + + public Task CreateTablesAsync(CancellationToken cancellationToken = default (CancellationToken)) + where T : new() + where T2 : new() + where T3 : new() + where T4 : new() + { + return CreateTablesAsync(cancellationToken, typeof(T), typeof(T2), typeof(T3), typeof(T4)); + } + + public Task CreateTablesAsync(CancellationToken cancellationToken = default (CancellationToken)) + where T : new() + where T2 : new() + where T3 : new() + where T4 : new() + where T5 : new() + { + return CreateTablesAsync(cancellationToken, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5)); + } + + public class CreateTablesResult + { + public Dictionary Results { get; private set; } + + internal CreateTablesResult() + { + this.Results = new Dictionary(); + } + } + + public Task CreateTablesAsync(params Type[] types) + { + return CreateTablesAsync(CancellationToken.None, types); + } + + public Task CreateTablesAsync(CancellationToken cancellationToken, params Type[] types) + { + if (types == null) + { + throw new ArgumentNullException("types"); + } + return Task.Factory.StartNew(() => + { + var result = new CreateTablesResult(); + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + foreach (Type type in types) + { + int aResult = conn.CreateTable(type); + result.Results[type] = aResult; + } + } + return result; + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task DropTableAsync(CancellationToken cancellationToken = default (CancellationToken)) + where T : new() + { + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + return conn.DropTable(); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task InsertAsync(object item, CancellationToken cancellationToken = default (CancellationToken)) + { + if (item == null) + { + throw new ArgumentNullException("item"); + } + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + return conn.Insert(item); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task UpdateAsync(object item, CancellationToken cancellationToken = default (CancellationToken)) + { + if (item == null) + { + throw new ArgumentNullException("item"); + } + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + return conn.Update(item); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task InsertOrReplaceAsync(object item, CancellationToken cancellationToken = default (CancellationToken)) + { + if (item == null) + { + throw new ArgumentNullException("item"); + } + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + return conn.InsertOrReplace(item); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task DeleteAsync(object item, CancellationToken cancellationToken = default (CancellationToken)) + { + if (item == null) + { + throw new ArgumentNullException("item"); + } + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + return conn.Delete(item); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task DeleteAllAsync(CancellationToken cancellationToken = default (CancellationToken)) + { + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + return conn.DeleteAll(); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task DeleteAsync(object pk, CancellationToken cancellationToken = default (CancellationToken)) + { + if (pk == null) + { + throw new ArgumentNullException("pk"); + } + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + return conn.Delete(pk); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task GetAsync(object pk, CancellationToken cancellationToken = default(CancellationToken)) + where T : new() + { + if (pk == null) + { + throw new ArgumentNullException("pk"); + } + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + cancellationToken.ThrowIfCancellationRequested(); + return conn.Get(pk); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task FindAsync(object pk, CancellationToken cancellationToken = default (CancellationToken)) + where T : new() + { + if (pk == null) + { + throw new ArgumentNullException("pk"); + } + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + cancellationToken.ThrowIfCancellationRequested(); + return conn.Find(pk); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task GetAsync(Expression> predicate, CancellationToken cancellationToken = default (CancellationToken)) + where T : new() + { + if (predicate == null) + { + throw new ArgumentNullException("predicate"); + } + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + cancellationToken.ThrowIfCancellationRequested(); + return conn.Get(predicate); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task FindAsync(Expression> predicate, CancellationToken cancellationToken = default(CancellationToken)) + where T : new() + { + if (predicate == null) + { + throw new ArgumentNullException("predicate"); + } + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + cancellationToken.ThrowIfCancellationRequested(); + return conn.Find(predicate); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task ExecuteAsync(string query, params object[] args) + { + return ExecuteAsync(CancellationToken.None, query, args); + } + + public Task ExecuteAsync(CancellationToken cancellationToken, string query, params object[] args) + { + if (query == null) + { + throw new ArgumentNullException("query"); + } + if (args == null) + { + throw new ArgumentNullException("args"); + } + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + return conn.Execute(query, args); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task InsertAllAsync(IEnumerable items, CancellationToken cancellationToken = default(CancellationToken)) + { + if (items == null) + { + throw new ArgumentNullException("items"); + } + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + return conn.InsertAll(items); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task InsertOrReplaceAllAsync(IEnumerable items, CancellationToken cancellationToken = default(CancellationToken)) + { + if (items == null) + { + throw new ArgumentNullException("items"); + } + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + return conn.InsertOrReplaceAll(items); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task UpdateAllAsync(IEnumerable items, CancellationToken cancellationToken = default(CancellationToken)) + { + if (items == null) + { + throw new ArgumentNullException("items"); + } + return Task.Factory.StartNew(() => + { + var conn = GetConnection(); + using (conn.Lock()) + { + return conn.UpdateAll(items); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + [Obsolete( + "Will cause a deadlock if any call in action ends up in a different thread. Use RunInTransactionAsync(Action) instead." + )] + public Task RunInTransactionAsync(Action action, CancellationToken cancellationToken = default(CancellationToken)) + { + if (action == null) + { + throw new ArgumentNullException("action"); + } + return Task.Factory.StartNew(() => + { + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + conn.BeginTransaction(); + try + { + action(this); + conn.Commit(); + } + catch (Exception) + { + conn.Rollback(); + throw; + } + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task RunInTransactionAsync(Action action, CancellationToken cancellationToken = default(CancellationToken)) + { + if (action == null) + { + throw new ArgumentNullException("action"); + } + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + cancellationToken.ThrowIfCancellationRequested(); + conn.BeginTransaction(); + try + { + action(conn); + conn.Commit(); + } + catch (Exception) + { + conn.Rollback(); + throw; + } + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public AsyncTableQuery Table() + where T : new() + { + // + // This isn't async as the underlying connection doesn't go out to the database + // until the query is performed. The Async methods are on the query iteself. + // + SQLiteConnectionWithLock conn = GetConnection(); + return new AsyncTableQuery(conn.Table(), _taskScheduler, _taskCreationOptions); + } + + public Task ExecuteScalarAsync(string sql, params object[] args) + { + return ExecuteScalarAsync(CancellationToken.None, sql, args); + } + + public Task ExecuteScalarAsync(CancellationToken cancellationToken, string sql, params object[] args) + { + if (sql == null) + { + throw new ArgumentNullException("sql"); + } + if (args == null) + { + throw new ArgumentNullException("args"); + } + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + cancellationToken.ThrowIfCancellationRequested(); + SQLiteCommand command = conn.CreateCommand(sql, args); + return command.ExecuteScalar(); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + + public Task> QueryAsync(string sql, params object[] args) + where T : new() + { + return QueryAsync (CancellationToken.None, sql, args); + } + + public Task> QueryAsync(CancellationToken cancellationToken, string sql, params object[] args) + where T : new() + { + if (sql == null) + { + throw new ArgumentNullException("sql"); + } + if (args == null) + { + throw new ArgumentNullException("args"); + } + return Task.Factory.StartNew(() => + { + cancellationToken.ThrowIfCancellationRequested(); + SQLiteConnectionWithLock conn = GetConnection(); + using (conn.Lock()) + { + cancellationToken.ThrowIfCancellationRequested(); + return conn.Query(sql, args); + } + }, cancellationToken, _taskCreationOptions, _taskScheduler ?? TaskScheduler.Default); + } + } +} diff --git a/src/SQLite.Net.Platform.Generic/Properties/AssemblyInfo.cs b/src/SQLite.Net.Platform.Generic/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..14d9c9317 --- /dev/null +++ b/src/SQLite.Net.Platform.Generic/Properties/AssemblyInfo.cs @@ -0,0 +1,13 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. +[assembly: AssemblyTitle ("SQLite.Net.Platform.Generic")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("James Ottaway")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] diff --git a/src/SQLite.Net.Platform.Generic/ReflectionServiceGeneric.cs b/src/SQLite.Net.Platform.Generic/ReflectionServiceGeneric.cs new file mode 100644 index 000000000..979d004fc --- /dev/null +++ b/src/SQLite.Net.Platform.Generic/ReflectionServiceGeneric.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Generic +{ + public class ReflectionServiceGeneric : IReflectionService + { + public IEnumerable GetPublicInstanceProperties(Type mappedType) + { + return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); + } + + public object GetMemberValue(object obj, Expression expr, MemberInfo member) + { + if (member.MemberType == MemberTypes.Property) + { + var m = (PropertyInfo) member; + return m.GetValue(obj, null); + } + if (member.MemberType == MemberTypes.Field) + { + var m = (FieldInfo) member; + return m.GetValue(obj); + } + throw new NotSupportedException("MemberExpr: " + member.MemberType); + } + } +} diff --git a/src/SQLite.Net.Platform.Generic/SQLite.Net.Platform.Generic.csproj b/src/SQLite.Net.Platform.Generic/SQLite.Net.Platform.Generic.csproj new file mode 100644 index 000000000..d420652b7 --- /dev/null +++ b/src/SQLite.Net.Platform.Generic/SQLite.Net.Platform.Generic.csproj @@ -0,0 +1,53 @@ + + + + Debug + AnyCPU + {F662E15A-8753-468E-A67E-3FCF45F12B89} + Library + SQLite.Net.Platform.Generic + SQLite.Net.Platform.Generic + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + full + true + bin\Release + prompt + 4 + false + + + + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + + + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Generic/SQLiteApiGeneric.cs b/src/SQLite.Net.Platform.Generic/SQLiteApiGeneric.cs new file mode 100644 index 000000000..6713c7c82 --- /dev/null +++ b/src/SQLite.Net.Platform.Generic/SQLiteApiGeneric.cs @@ -0,0 +1,241 @@ +using System; +using System.Runtime.InteropServices; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Generic +{ + public class SQLiteApiGeneric : ISQLiteApi + { + public Result Open(byte[] filename, out IDbHandle db, int flags, IntPtr zvfs) + { + IntPtr dbPtr; + Result r = SQLiteApiGenericInternal.sqlite3_open_v2(filename, out dbPtr, flags, zvfs); + db = new DbHandle(dbPtr); + return r; + } + + public ExtendedResult ExtendedErrCode(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiGenericInternal.sqlite3_extended_errcode(internalDbHandle.DbPtr); + } + + public int LibVersionNumber() + { + return SQLiteApiGenericInternal.sqlite3_libversion_number(); + } + + public Result EnableLoadExtension(IDbHandle db, int onoff) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiGenericInternal.sqlite3_enable_load_extension(internalDbHandle.DbPtr, onoff); + } + + public Result Close(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiGenericInternal.sqlite3_close(internalDbHandle.DbPtr); + } + public Result Initialize() + { + return SQLiteApiGenericInternal.sqlite3_initialize(); + } + public Result Shutdown() + { + return SQLiteApiGenericInternal.sqlite3_shutdown(); + } + + public Result Config(ConfigOption option) + { + return SQLiteApiGenericInternal.sqlite3_config(option); + } + + public Result BusyTimeout(IDbHandle db, int milliseconds) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiGenericInternal.sqlite3_busy_timeout(internalDbHandle.DbPtr, milliseconds); + } + + public int Changes(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiGenericInternal.sqlite3_changes(internalDbHandle.DbPtr); + } + + public IDbStatement Prepare2(IDbHandle db, string query) + { + var internalDbHandle = (DbHandle) db; + IntPtr stmt; + Result r = SQLiteApiGenericInternal.sqlite3_prepare_v2(internalDbHandle.DbPtr, query, query.Length, out stmt, IntPtr.Zero); + if (r != Result.OK) + { + throw SQLiteException.New(r, Errmsg16(internalDbHandle)); + } + return new DbStatement(stmt); + } + + public Result Step(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_step(internalStmt.StmtPtr); + } + + public Result Reset(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_reset(internalStmt.StmtPtr); + } + + public Result Finalize(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_finalize(internalStmt.StmtPtr); + } + + public long LastInsertRowid(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiGenericInternal.sqlite3_last_insert_rowid(internalDbHandle.DbPtr); + } + + public string Errmsg16(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return Marshal.PtrToStringUni(SQLiteApiGenericInternal.sqlite3_errmsg16(internalDbHandle.DbPtr)); + } + + public int BindParameterIndex(IDbStatement stmt, string name) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_bind_parameter_index(internalStmt.StmtPtr, name); + } + + public int BindNull(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_bind_null(internalStmt.StmtPtr, index); + } + + public int BindInt(IDbStatement stmt, int index, int val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_bind_int(internalStmt.StmtPtr, index, val); + } + + public int BindInt64(IDbStatement stmt, int index, long val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_bind_int64(internalStmt.StmtPtr, index, val); + } + + public int BindDouble(IDbStatement stmt, int index, double val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_bind_double(internalStmt.StmtPtr, index, val); + } + + public int BindText16(IDbStatement stmt, int index, string val, int n, IntPtr free) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_bind_text16(internalStmt.StmtPtr, index, val, n, free); + } + + public int BindBlob(IDbStatement stmt, int index, byte[] val, int n, IntPtr free) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_bind_blob(internalStmt.StmtPtr, index, val, n, free); + } + + public int ColumnCount(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_column_count(internalStmt.StmtPtr); + } + + public string ColumnName16(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.ColumnName16(internalStmt.StmtPtr, index); + } + + public ColType ColumnType(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_column_type(internalStmt.StmtPtr, index); + } + + public int ColumnInt(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_column_int(internalStmt.StmtPtr, index); + } + + public long ColumnInt64(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_column_int64(internalStmt.StmtPtr, index); + } + + public double ColumnDouble(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_column_double(internalStmt.StmtPtr, index); + } + + public string ColumnText16(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return Marshal.PtrToStringUni(SQLiteApiGenericInternal.sqlite3_column_text16(internalStmt.StmtPtr, index)); + } + + public byte[] ColumnBlob(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.ColumnBlob(internalStmt.StmtPtr, index); + } + + public int ColumnBytes(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.sqlite3_column_bytes(internalStmt.StmtPtr, index); + } + + public byte[] ColumnByteArray(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiGenericInternal.ColumnByteArray(internalStmt.StmtPtr, index); + } + + private struct DbHandle : IDbHandle + { + public DbHandle(IntPtr dbPtr) + : this() + { + DbPtr = dbPtr; + } + + internal IntPtr DbPtr { get; set; } + + public bool Equals(IDbHandle other) + { + return other is DbHandle && DbPtr == ((DbHandle) other).DbPtr; + } + } + + private struct DbStatement : IDbStatement + { + public DbStatement(IntPtr stmtPtr) + : this() + { + StmtPtr = stmtPtr; + } + + internal IntPtr StmtPtr { get; set; } + + public bool Equals(IDbStatement other) + { + return other is DbStatement && StmtPtr == ((DbStatement) other).StmtPtr; + } + } + } +} diff --git a/src/SQLite.Net.Platform.Generic/SQLiteApiGenericInternal.cs b/src/SQLite.Net.Platform.Generic/SQLiteApiGenericInternal.cs new file mode 100644 index 000000000..e4a21b0f4 --- /dev/null +++ b/src/SQLite.Net.Platform.Generic/SQLiteApiGenericInternal.cs @@ -0,0 +1,158 @@ +using System; +using System.Runtime.InteropServices; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Generic +{ + internal static class SQLiteApiGenericInternal + { + [DllImport("sqlite3", EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern byte[] ColumnBlob(IntPtr stmt, int index); + + public static byte[] ColumnByteArray(IntPtr stmt, int index) + { + int length = sqlite3_column_bytes(stmt, index); + var result = new byte[length]; + if (length > 0) + { + Marshal.Copy(sqlite3_column_blob(stmt, index), result, 0, length); + } + return result; + } + + public static string ColumnName16(IntPtr stmt, int index) + { + return Marshal.PtrToStringUni(sqlite3_column_name16(stmt, index)); + } + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_blob(IntPtr stmt, int index, byte[] val, int n, IntPtr free); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_double", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_double(IntPtr stmt, int index, double val); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_int(IntPtr stmt, int index, int val); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_int64", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_int64(IntPtr stmt, int index, long val); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_null", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_null(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_parameter_index", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_parameter_index(IntPtr stmt, [MarshalAs(UnmanagedType.LPStr)] string name); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_text16", CallingConvention = CallingConvention.Cdecl, + CharSet = CharSet.Unicode)] + public static extern int sqlite3_bind_text16(IntPtr stmt, + int index, + [MarshalAs(UnmanagedType.LPWStr)] string val, + int n, + IntPtr free); + + [DllImport("sqlite3", EntryPoint = "sqlite3_busy_timeout", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_busy_timeout(IntPtr db, int milliseconds); + + [DllImport("sqlite3", EntryPoint = "sqlite3_changes", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_changes(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_close", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_close(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_initialize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_initialize(); + + [DllImport("sqlite3", EntryPoint = "sqlite3_shutdown", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_shutdown(); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_column_blob(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_bytes", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_bytes(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_count", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_count(IntPtr stmt); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_double", CallingConvention = CallingConvention.Cdecl)] + public static extern double sqlite3_column_double(IntPtr stmt, int index); + + // [DllImport("sqlite3", EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + // private extern IntPtr ColumnNameInternal(IntPtr stmt, int index); + + // [DllImport("sqlite3", EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + // public string ColumnName(IntPtr stmt, int index) + // { + // return ColumnNameInternal(stmt, index); + // } + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_int(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_int64", CallingConvention = CallingConvention.Cdecl)] + public static extern long sqlite3_column_int64(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_text16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_column_text16(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_type", CallingConvention = CallingConvention.Cdecl)] + public static extern ColType sqlite3_column_type(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_config", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_config(ConfigOption option); + + [DllImport("sqlite3", EntryPoint = "sqlite3_enable_load_extension", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_enable_load_extension(IntPtr db, int onoff); + + [DllImport("sqlite3", EntryPoint = "sqlite3_errmsg16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_errmsg16(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_finalize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_finalize(IntPtr stmt); + + [DllImport("sqlite3", EntryPoint = "sqlite3_last_insert_rowid", CallingConvention = CallingConvention.Cdecl)] + public static extern long sqlite3_last_insert_rowid(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_open", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport("sqlite3", EntryPoint = "sqlite3_open16", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open16([MarshalAs(UnmanagedType.LPWStr)] string filename, out IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open_v2(byte[] filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport("sqlite3", EntryPoint = "sqlite3_prepare_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_prepare_v2(IntPtr db, + [MarshalAs(UnmanagedType.LPStr)] string sql, + int numBytes, + out IntPtr stmt, + IntPtr pzTail); + + [DllImport("sqlite3", EntryPoint = "sqlite3_reset", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_reset(IntPtr stmt); + + [DllImport("sqlite3", EntryPoint = "sqlite3_step", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_step(IntPtr stmt); + + [DllImport("sqlite3", EntryPoint = "sqlite3_win32_set_directory", CallingConvention = CallingConvention.Cdecl, + CharSet = CharSet.Unicode)] + public static extern int sqlite3_win32_set_directory(uint directoryType, string directoryPath); + + [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern IntPtr LoadLibrary(string lpFileName); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_name16", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr sqlite3_column_name16(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_extended_errcode", CallingConvention = CallingConvention.Cdecl)] + public static extern ExtendedResult sqlite3_extended_errcode(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_libversion_number", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_libversion_number(); + } +} diff --git a/src/SQLite.Net.Platform.Generic/SQLitePlatformGeneric.cs b/src/SQLite.Net.Platform.Generic/SQLitePlatformGeneric.cs new file mode 100644 index 000000000..63cc1b32e --- /dev/null +++ b/src/SQLite.Net.Platform.Generic/SQLitePlatformGeneric.cs @@ -0,0 +1,20 @@ +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Generic +{ + public class SQLitePlatformGeneric : ISQLitePlatform + { + public SQLitePlatformGeneric() + { + SQLiteApi = new SQLiteApiGeneric(); + StopwatchFactory = new StopwatchFactoryGeneric(); + ReflectionService = new ReflectionServiceGeneric(); + VolatileService = new VolatileServiceGeneric(); + } + + public ISQLiteApi SQLiteApi { get; private set; } + public IStopwatchFactory StopwatchFactory { get; private set; } + public IReflectionService ReflectionService { get; private set; } + public IVolatileService VolatileService { get; private set; } + } +} diff --git a/src/SQLite.Net.Platform.Generic/StopwatchFactoryGeneric.cs b/src/SQLite.Net.Platform.Generic/StopwatchFactoryGeneric.cs new file mode 100644 index 000000000..1ec0c6b5b --- /dev/null +++ b/src/SQLite.Net.Platform.Generic/StopwatchFactoryGeneric.cs @@ -0,0 +1,43 @@ +using System.Diagnostics; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Generic +{ + public class StopwatchFactoryGeneric : IStopwatchFactory + { + public IStopwatch Create() + { + return new StopwatchGeneric(); + } + + private class StopwatchGeneric : IStopwatch + { + private readonly Stopwatch _stopWatch; + + public StopwatchGeneric() + { + _stopWatch = new Stopwatch(); + } + + public void Stop() + { + _stopWatch.Stop(); + } + + public void Reset() + { + _stopWatch.Reset(); + } + + public void Start() + { + _stopWatch.Start(); + } + + public long ElapsedMilliseconds + { + get { return _stopWatch.ElapsedMilliseconds; } + } + } + } +} diff --git a/src/SQLite.Net.Platform.Generic/VolatileServiceGeneric.cs b/src/SQLite.Net.Platform.Generic/VolatileServiceGeneric.cs new file mode 100644 index 000000000..c80ab5d3f --- /dev/null +++ b/src/SQLite.Net.Platform.Generic/VolatileServiceGeneric.cs @@ -0,0 +1,13 @@ +using System.Threading; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Generic +{ + public class VolatileServiceGeneric : IVolatileService + { + public void Write(ref int transactionDepth, int depth) + { + Thread.VolatileWrite(ref transactionDepth, depth); + } + } +} diff --git a/src/SQLite.Net.Platform.Win32/Properties/AssemblyInfo.cs b/src/SQLite.Net.Platform.Win32/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..51f088575 --- /dev/null +++ b/src/SQLite.Net.Platform.Win32/Properties/AssemblyInfo.cs @@ -0,0 +1,25 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("SQLite.Net.Platform.Win32")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Øystein Krog")] +[assembly: AssemblyProduct("SQLite.Net.Platform.Win32")] +[assembly: AssemblyCopyright("Copyright © Øystein Krog")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("4f906778-2564-403a-81d7-1b8ba8c2cee6")] \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/ReflectionServiceWin32.cs b/src/SQLite.Net.Platform.Win32/ReflectionServiceWin32.cs new file mode 100644 index 000000000..2373274d3 --- /dev/null +++ b/src/SQLite.Net.Platform.Win32/ReflectionServiceWin32.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Win32 +{ + public class ReflectionServiceWin32 : IReflectionService + { + public IEnumerable GetPublicInstanceProperties(Type mappedType) + { + return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); + } + + public object GetMemberValue(object obj, Expression expr, MemberInfo member) + { + if (member.MemberType == MemberTypes.Property) + { + var m = (PropertyInfo) member; + return m.GetValue(obj, null); + } + if (member.MemberType == MemberTypes.Field) + { + var m = (FieldInfo) member; + return m.GetValue(obj); + } + throw new NotSupportedException("MemberExpr: " + member.MemberType); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/SQLite.Net.Platform.Win32.csproj b/src/SQLite.Net.Platform.Win32/SQLite.Net.Platform.Win32.csproj new file mode 100644 index 000000000..925838472 --- /dev/null +++ b/src/SQLite.Net.Platform.Win32/SQLite.Net.Platform.Win32.csproj @@ -0,0 +1,85 @@ + + + + + Debug + AnyCPU + {03799AD1-9FCF-48CB-8E6E-B233DF583B10} + Library + Properties + SQLite.Net.Platform.Win32 + SQLite.Net.Platform.Win32 + v4.5 + 512 + + ..\..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + ..\..\packages\System.Data.SQLite.Core.1.0.92.0\lib\net40\System.Data.SQLite.dll + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + + + Always + + + Always + + + + + + + + + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/SQLiteApiWin32.cs b/src/SQLite.Net.Platform.Win32/SQLiteApiWin32.cs new file mode 100644 index 000000000..6859f0fce --- /dev/null +++ b/src/SQLite.Net.Platform.Win32/SQLiteApiWin32.cs @@ -0,0 +1,241 @@ +using System; +using System.Runtime.InteropServices; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Win32 +{ + public class SQLiteApiWin32 : ISQLiteApi + { + public Result Open(byte[] filename, out IDbHandle db, int flags, IntPtr zvfs) + { + IntPtr dbPtr; + Result r = SQLiteApiWin32Internal.sqlite3_open_v2(filename, out dbPtr, flags, zvfs); + db = new DbHandle(dbPtr); + return r; + } + + public ExtendedResult ExtendedErrCode(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiWin32Internal.sqlite3_extended_errcode(internalDbHandle.DbPtr); + } + + public int LibVersionNumber() + { + return SQLiteApiWin32Internal.sqlite3_libversion_number(); + } + + public Result EnableLoadExtension(IDbHandle db, int onoff) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiWin32Internal.sqlite3_enable_load_extension(internalDbHandle.DbPtr, onoff); + } + + public Result Close(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiWin32Internal.sqlite3_close(internalDbHandle.DbPtr); + } + + public Result Initialize() + { + return SQLiteApiWin32Internal.sqlite3_initialize(); + } + public Result Shutdown() + { + return SQLiteApiWin32Internal.sqlite3_shutdown(); + } + + public Result Config(ConfigOption option) + { + return SQLiteApiWin32Internal.sqlite3_config(option); + } + + + public Result BusyTimeout(IDbHandle db, int milliseconds) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiWin32Internal.sqlite3_busy_timeout(internalDbHandle.DbPtr, milliseconds); + } + + public int Changes(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiWin32Internal.sqlite3_changes(internalDbHandle.DbPtr); + } + + public IDbStatement Prepare2(IDbHandle db, string query) + { + var internalDbHandle = (DbHandle) db; + IntPtr stmt; + Result r = SQLiteApiWin32Internal.sqlite3_prepare_v2(internalDbHandle.DbPtr, query, query.Length, out stmt, IntPtr.Zero); + if (r != Result.OK) + { + throw SQLiteException.New(r, Errmsg16(internalDbHandle)); + } + return new DbStatement(stmt); + } + + public Result Step(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_step(internalStmt.StmtPtr); + } + + public Result Reset(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_reset(internalStmt.StmtPtr); + } + + public Result Finalize(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_finalize(internalStmt.StmtPtr); + } + + public long LastInsertRowid(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiWin32Internal.sqlite3_last_insert_rowid(internalDbHandle.DbPtr); + } + + public string Errmsg16(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return Marshal.PtrToStringUni(SQLiteApiWin32Internal.sqlite3_errmsg16(internalDbHandle.DbPtr)); + } + + public int BindParameterIndex(IDbStatement stmt, string name) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_bind_parameter_index(internalStmt.StmtPtr, name); + } + + public int BindNull(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_bind_null(internalStmt.StmtPtr, index); + } + + public int BindInt(IDbStatement stmt, int index, int val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_bind_int(internalStmt.StmtPtr, index, val); + } + + public int BindInt64(IDbStatement stmt, int index, long val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_bind_int64(internalStmt.StmtPtr, index, val); + } + + public int BindDouble(IDbStatement stmt, int index, double val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_bind_double(internalStmt.StmtPtr, index, val); + } + + public int BindText16(IDbStatement stmt, int index, string val, int n, IntPtr free) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_bind_text16(internalStmt.StmtPtr, index, val, n, free); + } + + public int BindBlob(IDbStatement stmt, int index, byte[] val, int n, IntPtr free) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_bind_blob(internalStmt.StmtPtr, index, val, n, free); + } + + public int ColumnCount(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_column_count(internalStmt.StmtPtr); + } + + public string ColumnName16(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.ColumnName16(internalStmt.StmtPtr, index); + } + + public ColType ColumnType(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_column_type(internalStmt.StmtPtr, index); + } + + public int ColumnInt(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_column_int(internalStmt.StmtPtr, index); + } + + public long ColumnInt64(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_column_int64(internalStmt.StmtPtr, index); + } + + public double ColumnDouble(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_column_double(internalStmt.StmtPtr, index); + } + + public string ColumnText16(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return Marshal.PtrToStringUni(SQLiteApiWin32Internal.sqlite3_column_text16(internalStmt.StmtPtr, index)); + } + + public byte[] ColumnBlob(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.ColumnBlob(internalStmt.StmtPtr, index); + } + + public int ColumnBytes(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.sqlite3_column_bytes(internalStmt.StmtPtr, index); + } + + public byte[] ColumnByteArray(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiWin32Internal.ColumnByteArray(internalStmt.StmtPtr, index); + } + + private struct DbHandle : IDbHandle + { + public DbHandle(IntPtr dbPtr) : this() + { + DbPtr = dbPtr; + } + + internal IntPtr DbPtr { get; set; } + + public bool Equals(IDbHandle other) + { + return other is DbHandle && DbPtr == ((DbHandle) other).DbPtr; + } + } + + private struct DbStatement : IDbStatement + { + public DbStatement(IntPtr stmtPtr) : this() + { + StmtPtr = stmtPtr; + } + + internal IntPtr StmtPtr { get; set; } + + public bool Equals(IDbStatement other) + { + return other is DbStatement && StmtPtr == ((DbStatement) other).StmtPtr; + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/SQLitePlatformWin32.cs b/src/SQLite.Net.Platform.Win32/SQLitePlatformWin32.cs new file mode 100644 index 000000000..f1de83dbb --- /dev/null +++ b/src/SQLite.Net.Platform.Win32/SQLitePlatformWin32.cs @@ -0,0 +1,20 @@ +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Win32 +{ + public class SQLitePlatformWin32 : ISQLitePlatform + { + public SQLitePlatformWin32() + { + SQLiteApi = new SQLiteApiWin32(); + StopwatchFactory = new StopwatchFactoryWin32(); + ReflectionService = new ReflectionServiceWin32(); + VolatileService = new VolatileServiceWin32(); + } + + public ISQLiteApi SQLiteApi { get; private set; } + public IStopwatchFactory StopwatchFactory { get; private set; } + public IReflectionService ReflectionService { get; private set; } + public IVolatileService VolatileService { get; private set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/SQliteApiWin32Internal.cs b/src/SQLite.Net.Platform.Win32/SQliteApiWin32Internal.cs new file mode 100644 index 000000000..097c4720a --- /dev/null +++ b/src/SQLite.Net.Platform.Win32/SQliteApiWin32Internal.cs @@ -0,0 +1,194 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using SQLite.Net.Interop; +using System.Reflection; + +namespace SQLite.Net.Platform.Win32 +{ + internal static class SQLiteApiWin32Internal + { + static SQLiteApiWin32Internal() + { + // load native library + int ptrSize = Marshal.SizeOf(typeof (IntPtr)); + string relativePath = ptrSize == 8 ? @"x64\SQLite.Interop.dll" : @"x86\SQLite.Interop.dll"; + string assemblyCurrentPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + string assemblyInteropPath = Path.Combine(assemblyCurrentPath, relativePath); + + // try relative to assembly first, if that does not exist try relative to working dir + string interopPath = File.Exists(assemblyInteropPath) ? assemblyInteropPath : relativePath; + + IntPtr ret = LoadLibrary(interopPath); + if (ret == IntPtr.Zero) + { + throw new Exception("Failed to load native sqlite library"); + } + } + + [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern IntPtr LoadLibrary(string lpFileName); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_open", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db, + int flags, + IntPtr zvfs); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_open16", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open16([MarshalAs(UnmanagedType.LPWStr)] string filename, out IntPtr db); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_enable_load_extension", + CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_enable_load_extension(IntPtr db, int onoff); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_close", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_close(IntPtr db); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_initialize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_initialize(); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_shutdown", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_shutdown(); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_config", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_config(ConfigOption option); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_win32_set_directory", + CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern int sqlite3_win32_set_directory(uint directoryType, string directoryPath); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_busy_timeout", + CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_busy_timeout(IntPtr db, int milliseconds); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_changes", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_changes(IntPtr db); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_prepare_v2", CallingConvention = CallingConvention.Cdecl) + ] + public static extern Result sqlite3_prepare_v2(IntPtr db, [MarshalAs(UnmanagedType.LPStr)] string sql, + int numBytes, + out IntPtr stmt, IntPtr pzTail); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_step", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_step(IntPtr stmt); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_reset", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_reset(IntPtr stmt); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_finalize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_finalize(IntPtr stmt); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_last_insert_rowid", + CallingConvention = CallingConvention.Cdecl)] + public static extern long sqlite3_last_insert_rowid(IntPtr db); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_errmsg16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_errmsg16(IntPtr db); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_bind_parameter_index", + CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_parameter_index(IntPtr stmt, [MarshalAs(UnmanagedType.LPStr)] string name); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_bind_null", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_null(IntPtr stmt, int index); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_bind_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_int(IntPtr stmt, int index, int val); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_bind_int64", CallingConvention = CallingConvention.Cdecl) + ] + public static extern int sqlite3_bind_int64(IntPtr stmt, int index, long val); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_bind_double", CallingConvention = CallingConvention.Cdecl + )] + public static extern int sqlite3_bind_double(IntPtr stmt, int index, double val); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_bind_text16", CallingConvention = CallingConvention.Cdecl, + CharSet = CharSet.Unicode)] + public static extern int sqlite3_bind_text16(IntPtr stmt, int index, + [MarshalAs(UnmanagedType.LPWStr)] string val, + int n, + IntPtr free); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_bind_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_blob(IntPtr stmt, int index, byte[] val, int n, IntPtr free); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_count", + CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_count(IntPtr stmt); + + // [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + // private extern IntPtr ColumnNameInternal(IntPtr stmt, int index); + + // [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + // public string ColumnName(IntPtr stmt, int index) + // { + // return ColumnNameInternal(stmt, index); + // } + + public static string ColumnName16(IntPtr stmt, int index) + { + return Marshal.PtrToStringUni(sqlite3_column_name16(stmt, index)); + } + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_type", CallingConvention = CallingConvention.Cdecl + )] + public static extern ColType sqlite3_column_type(IntPtr stmt, int index); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_int", CallingConvention = CallingConvention.Cdecl) + ] + public static extern int sqlite3_column_int(IntPtr stmt, int index); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_int64", + CallingConvention = CallingConvention.Cdecl)] + public static extern long sqlite3_column_int64(IntPtr stmt, int index); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_double", + CallingConvention = CallingConvention.Cdecl)] + public static extern double sqlite3_column_double(IntPtr stmt, int index); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_text16", + CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_column_text16(IntPtr stmt, int index); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl + )] + public static extern byte[] ColumnBlob(IntPtr stmt, int index); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl + )] + public static extern IntPtr sqlite3_column_blob(IntPtr stmt, int index); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_bytes", + CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_bytes(IntPtr stmt, int index); + + public static byte[] ColumnByteArray(IntPtr stmt, int index) + { + int length = sqlite3_column_bytes(stmt, index); + var result = new byte[length]; + if (length > 0) + { + Marshal.Copy(sqlite3_column_blob(stmt, index), result, 0, length); + } + return result; + } + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open_v2(byte[] filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_column_name16", + CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr sqlite3_column_name16(IntPtr stmt, int index); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_extended_errcode", CallingConvention = CallingConvention.Cdecl)] + public static extern ExtendedResult sqlite3_extended_errcode(IntPtr db); + + [DllImport("SQLite.Interop.dll", EntryPoint = "sqlite3_libversion_number", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_libversion_number(); + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/StopwatchFactoryWin32.cs b/src/SQLite.Net.Platform.Win32/StopwatchFactoryWin32.cs new file mode 100644 index 000000000..91e2fed72 --- /dev/null +++ b/src/SQLite.Net.Platform.Win32/StopwatchFactoryWin32.cs @@ -0,0 +1,43 @@ +using System.Diagnostics; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Win32 +{ + public class StopwatchFactoryWin32 : IStopwatchFactory + { + public IStopwatch Create() + { + return new StopwatchWin32(); + } + + private class StopwatchWin32 : IStopwatch + { + private readonly Stopwatch _stopWatch; + + public StopwatchWin32() + { + _stopWatch = new Stopwatch(); + } + + public void Stop() + { + _stopWatch.Stop(); + } + + public void Reset() + { + _stopWatch.Reset(); + } + + public void Start() + { + _stopWatch.Start(); + } + + public long ElapsedMilliseconds + { + get { return _stopWatch.ElapsedMilliseconds; } + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/VolatileServiceWin32.cs b/src/SQLite.Net.Platform.Win32/VolatileServiceWin32.cs new file mode 100644 index 000000000..277ff6e76 --- /dev/null +++ b/src/SQLite.Net.Platform.Win32/VolatileServiceWin32.cs @@ -0,0 +1,13 @@ +using System.Threading; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.Win32 +{ + public class VolatileServiceWin32 : IVolatileService + { + public void Write(ref int transactionDepth, int depth) + { + Thread.VolatileWrite(ref transactionDepth, depth); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/packages.config b/src/SQLite.Net.Platform.Win32/packages.config new file mode 100644 index 000000000..e9dea1fba --- /dev/null +++ b/src/SQLite.Net.Platform.Win32/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/x64/SQLite.Interop.dll b/src/SQLite.Net.Platform.Win32/x64/SQLite.Interop.dll new file mode 100644 index 000000000..a50b4cebc Binary files /dev/null and b/src/SQLite.Net.Platform.Win32/x64/SQLite.Interop.dll differ diff --git a/src/SQLite.Net.Platform.Win32/x86/SQLite.Interop.dll b/src/SQLite.Net.Platform.Win32/x86/SQLite.Interop.dll new file mode 100644 index 000000000..0781c5a43 Binary files /dev/null and b/src/SQLite.Net.Platform.Win32/x86/SQLite.Interop.dll differ diff --git a/src/SQLite.Net.Platform.WinRT/Properties/AssemblyInfo.cs b/src/SQLite.Net.Platform.WinRT/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..1c859c486 --- /dev/null +++ b/src/SQLite.Net.Platform.WinRT/Properties/AssemblyInfo.cs @@ -0,0 +1,14 @@ +using System.Reflection; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("SQLite.Net.Platform.WinRT")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Øystein Krog")] +[assembly: AssemblyProduct("SQLite.Net.Platform.WinRT")] +[assembly: AssemblyCopyright("Copyright © Øystein Krog")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/SQLite.Net.Platform.WinRT/ReflectionServiceWinRT.cs b/src/SQLite.Net.Platform.WinRT/ReflectionServiceWinRT.cs new file mode 100644 index 000000000..2ba36382b --- /dev/null +++ b/src/SQLite.Net.Platform.WinRT/ReflectionServiceWinRT.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.WinRT +{ + public class ReflectionServiceWinRT : IReflectionService + { + public IEnumerable GetPublicInstanceProperties(Type mappedType) + { + return from p in mappedType.GetRuntimeProperties() + where + ((p.GetMethod != null && p.GetMethod.IsPublic) || (p.SetMethod != null && p.SetMethod.IsPublic) || + (p.GetMethod != null && p.GetMethod.IsStatic) || (p.SetMethod != null && p.SetMethod.IsStatic)) + select p; + } + + public object GetMemberValue(object obj, Expression expr, MemberInfo member) + { + if (member is PropertyInfo) + { + var m = (PropertyInfo) member; + return m.GetValue(obj, null); + } + if (member is FieldInfo) + { + var m = (FieldInfo) member; + return m.GetValue(obj); + } + throw new NotSupportedException("MemberExpr: " + member.DeclaringType); + } + } +} \ No newline at end of file diff --git a/tests/SQLiteMetroTests/SQLiteMetroTests.csproj b/src/SQLite.Net.Platform.WinRT/SQLite.Net.Platform.WinRT.csproj similarity index 55% rename from tests/SQLiteMetroTests/SQLiteMetroTests.csproj rename to src/SQLite.Net.Platform.WinRT/SQLite.Net.Platform.WinRT.csproj index 7d9abf57c..7238d32e6 100644 --- a/tests/SQLiteMetroTests/SQLiteMetroTests.csproj +++ b/src/SQLite.Net.Platform.WinRT/SQLite.Net.Platform.WinRT.csproj @@ -6,16 +6,18 @@ AnyCPU 8.0.30703 2.0 - {909DE315-2F55-4A20-A9AD-460D4B2A3908} + {6891E212-AEEE-4763-AC6F-BD7213C13890} Library Properties - SQLiteMetroTests - SQLiteMetroTests + SQLite.Net.Platform.WinRT + SQLite.Net.Platform.WinRT en-US + 8.1 + 12 512 {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - SQLiteMetroTests_TemporaryKey.pfx - DFDDA4814A991B0900EDBDBBB55A3C0DC34968D9 + ..\..\ + true true @@ -43,7 +45,6 @@ ARM false prompt - ExpressRules.ruleset true @@ -55,7 +56,6 @@ ARM false prompt - ExpressRules.ruleset true @@ -67,7 +67,6 @@ x64 false prompt - ExpressRules.ruleset true @@ -79,7 +78,6 @@ x64 false prompt - ExpressRules.ruleset true @@ -91,7 +89,6 @@ x86 false prompt - ExpressRules.ruleset true @@ -103,116 +100,35 @@ x86 false prompt - ExpressRules.ruleset true - - True - - - - + + + {ABF3D656-3D1C-45D1-B6FD-41B088E5A533} + SQLite.Net + - - SQLite.cs - - - SQLiteAsync.cs - - - AsyncTests.cs - - - BooleanTest.cs - - - ByteArrayTest.cs - - - CollateTest.cs - - - ContainsTest.cs - - - CreateTableTest.cs - - - DropTableTest.cs - - - ExceptionAssert.cs - - - GuidTests.cs - - - InheritanceTest.cs - - - InsertTest.cs - - - LinqTest.cs - - - MappingTest.cs - - - NullableTest.cs - - - SkipTest.cs - - - StringQueryTest.cs - - - TestDb.cs - - - UnicodeTest.cs - - - UniqueTest.cs + + Properties\GlobalAssemblyInfo.cs + + + + + - - - Designer - - - - - sqlite3.dll - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - - - - 11.0 + + 12.0 + diff --git a/src/SQLite.Net.Platform.WinRT/SQLiteApiWinRT.cs b/src/SQLite.Net.Platform.WinRT/SQLiteApiWinRT.cs new file mode 100644 index 000000000..441f73f7f --- /dev/null +++ b/src/SQLite.Net.Platform.WinRT/SQLiteApiWinRT.cs @@ -0,0 +1,380 @@ +using System; +using SQLite.Net.Interop; +using System.Runtime.InteropServices; +using System.Text; +using Sqlite3DatabaseHandle = System.IntPtr; +using Sqlite3Statement = System.IntPtr; + +namespace SQLite.Net.Platform.WinRT +{ + public class SQLiteApiWinRT : ISQLiteApi + { + public int BindBlob(IDbStatement stmt, int index, byte[] val, int n, IntPtr free) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.BindBlob(dbStatement.InternalStmt, index, val, n, free); + } + + public int BindDouble(IDbStatement stmt, int index, double val) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.BindDouble(dbStatement.InternalStmt, index, val); + } + + public int BindInt(IDbStatement stmt, int index, int val) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.BindInt(dbStatement.InternalStmt, index, val); + } + + public int BindInt64(IDbStatement stmt, int index, long val) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.BindInt64(dbStatement.InternalStmt, index, val); + } + + public int BindNull(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.BindNull(dbStatement.InternalStmt, index); + } + + public int BindParameterIndex(IDbStatement stmt, string name) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.BindParameterIndex(dbStatement.InternalStmt, name); + } + + public int BindText16(IDbStatement stmt, int index, string val, int n, IntPtr free) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.BindText(dbStatement.InternalStmt, index, val, n, free); + } + + public Result BusyTimeout(IDbHandle db, int milliseconds) + { + var dbHandle = (DbHandle)db; + return (Result)SQLite3.BusyTimeout(dbHandle.InternalDbHandle, milliseconds); + } + + public int Changes(IDbHandle db) + { + var dbHandle = (DbHandle)db; + return SQLite3.Changes(dbHandle.InternalDbHandle); + } + + public Result Close(IDbHandle db) + { + var dbHandle = (DbHandle)db; + return (Result)SQLite3.Close(dbHandle.InternalDbHandle); + } + + public Result Initialize() + { + throw new NotSupportedException(); + } + public Result Shutdown() + { + throw new NotSupportedException(); + } + + public Result Config(ConfigOption option) + { + return (Result)SQLite3.Config(option); + } + + + public byte[] ColumnBlob(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + int length = ColumnBytes(stmt, index); + byte[] result = new byte[length]; + if (length > 0) + Marshal.Copy(SQLite3.ColumnBlob(dbStatement.InternalStmt, index), result, 0, length); + return result; + } + + public byte[] ColumnByteArray(IDbStatement stmt, int index) + { + return ColumnBlob(stmt, index); + } + + public int ColumnBytes(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.ColumnBytes(dbStatement.InternalStmt, index); + } + + public int ColumnCount(IDbStatement stmt) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.ColumnCount(dbStatement.InternalStmt); + } + + public double ColumnDouble(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.ColumnDouble(dbStatement.InternalStmt, index); + } + + public int ColumnInt(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.ColumnInt(dbStatement.InternalStmt, index); + } + + public long ColumnInt64(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.ColumnInt64(dbStatement.InternalStmt, index); + } + + public string ColumnName16(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return SQLite3.ColumnName16(dbStatement.InternalStmt, index); + } + + public string ColumnText16(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Marshal.PtrToStringUni(SQLite3.ColumnText16(dbStatement.InternalStmt, index)); + } + + public ColType ColumnType(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return (ColType)SQLite3.ColumnType(dbStatement.InternalStmt, index); + } + + public int LibVersionNumber() + { + return SQLite3.sqlite3_libversion_number(); + } + + public Result EnableLoadExtension(IDbHandle db, int onoff) + { + return (Result)1; + } + + public string Errmsg16(IDbHandle db) + { + var dbHandle = (DbHandle)db; + return SQLite3.GetErrmsg(dbHandle.InternalDbHandle); + } + + public Result Finalize(IDbStatement stmt) + { + var dbStatement = (DbStatement)stmt; + Sqlite3Statement internalStmt = dbStatement.InternalStmt; + return (Result)SQLite3.Finalize(internalStmt); + } + + public long LastInsertRowid(IDbHandle db) + { + var dbHandle = (DbHandle)db; + return SQLite3.LastInsertRowid(dbHandle.InternalDbHandle); + } + + public Result Open(byte[] filename, out IDbHandle db, int flags, IntPtr zvfs) + { + Sqlite3DatabaseHandle internalDbHandle; + var ret = (Result)SQLite3.Open(filename, out internalDbHandle, flags, zvfs); + db = new DbHandle(internalDbHandle); + return ret; + } + + public ExtendedResult ExtendedErrCode(IDbHandle db) + { + var dbHandle = (DbHandle)db; + return SQLite3.sqlite3_extended_errcode(dbHandle.InternalDbHandle); + } + + public IDbStatement Prepare2(IDbHandle db, string query) + { + var dbHandle = (DbHandle)db; + var stmt = default(Sqlite3Statement); + var r = SQLite3.Prepare2(dbHandle.InternalDbHandle, query, query.Length, out stmt, IntPtr.Zero); + if (r != Result.OK) + { + throw SQLiteException.New(r, SQLite3.GetErrmsg(dbHandle.InternalDbHandle)); + } + return new DbStatement(stmt); + } + + public Result Reset(IDbStatement stmt) + { + var dbStatement = (DbStatement)stmt; + return (Result)SQLite3.Reset(dbStatement.InternalStmt); + } + + public Result Step(IDbStatement stmt) + { + var dbStatement = (DbStatement)stmt; + return (Result)SQLite3.Step(dbStatement.InternalStmt); + } + + private struct DbHandle : IDbHandle + { + public DbHandle(Sqlite3DatabaseHandle internalDbHandle) + : this() + { + InternalDbHandle = internalDbHandle; + } + + public Sqlite3DatabaseHandle InternalDbHandle { get; set; } + + public bool Equals(IDbHandle other) + { + return other is DbHandle && InternalDbHandle == ((DbHandle)other).InternalDbHandle; + } + } + + private struct DbStatement : IDbStatement + { + public DbStatement(Sqlite3Statement internalStmt) + : this() + { + InternalStmt = internalStmt; + } + + internal Sqlite3Statement InternalStmt { get; set; } + + public bool Equals(IDbStatement other) + { + return (other is DbStatement) && ((DbStatement)other).InternalStmt == InternalStmt; + } + } + } + + public static class SQLite3 + { + [DllImport("sqlite3", EntryPoint = "sqlite3_open", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport("sqlite3", EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Open(byte[] filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport("sqlite3", EntryPoint = "sqlite3_open16", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Open16([MarshalAs(UnmanagedType.LPWStr)] string filename, out IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_close", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Close(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_config", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Config(ConfigOption option); + + [DllImport("sqlite3", EntryPoint = "sqlite3_win32_set_directory", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern int SetDirectory(uint directoryType, string directoryPath); + + [DllImport("sqlite3", EntryPoint = "sqlite3_busy_timeout", CallingConvention = CallingConvention.Cdecl)] + public static extern Result BusyTimeout(IntPtr db, int milliseconds); + + [DllImport("sqlite3", EntryPoint = "sqlite3_changes", CallingConvention = CallingConvention.Cdecl)] + public static extern int Changes(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_prepare_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Prepare2(IntPtr db, [MarshalAs(UnmanagedType.LPStr)] string sql, int numBytes, out IntPtr stmt, IntPtr pzTail); + + [DllImport("sqlite3", EntryPoint = "sqlite3_step", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Step(IntPtr stmt); + + [DllImport("sqlite3", EntryPoint = "sqlite3_reset", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Reset(IntPtr stmt); + + [DllImport("sqlite3", EntryPoint = "sqlite3_finalize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Finalize(IntPtr stmt); + + [DllImport("sqlite3", EntryPoint = "sqlite3_last_insert_rowid", CallingConvention = CallingConvention.Cdecl)] + public static extern long LastInsertRowid(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_errmsg16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr Errmsg(IntPtr db); + + public static string GetErrmsg(IntPtr db) + { + return Marshal.PtrToStringUni(Errmsg(db)); + } + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_parameter_index", CallingConvention = CallingConvention.Cdecl)] + public static extern int BindParameterIndex(IntPtr stmt, [MarshalAs(UnmanagedType.LPStr)] string name); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_null", CallingConvention = CallingConvention.Cdecl)] + public static extern int BindNull(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int BindInt(IntPtr stmt, int index, int val); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_int64", CallingConvention = CallingConvention.Cdecl)] + public static extern int BindInt64(IntPtr stmt, int index, long val); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_double", CallingConvention = CallingConvention.Cdecl)] + public static extern int BindDouble(IntPtr stmt, int index, double val); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_text16", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern int BindText(IntPtr stmt, int index, [MarshalAs(UnmanagedType.LPWStr)] string val, int n, IntPtr free); + + [DllImport("sqlite3", EntryPoint = "sqlite3_bind_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern int BindBlob(IntPtr stmt, int index, byte[] val, int n, IntPtr free); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_count", CallingConvention = CallingConvention.Cdecl)] + public static extern int ColumnCount(IntPtr stmt); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ColumnName(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_name16", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr ColumnName16Internal(IntPtr stmt, int index); + public static string ColumnName16(IntPtr stmt, int index) + { + return Marshal.PtrToStringUni(ColumnName16Internal(stmt, index)); + } + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_type", CallingConvention = CallingConvention.Cdecl)] + public static extern ColType ColumnType(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int ColumnInt(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_int64", CallingConvention = CallingConvention.Cdecl)] + public static extern long ColumnInt64(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_double", CallingConvention = CallingConvention.Cdecl)] + public static extern double ColumnDouble(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_text", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ColumnText(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_text16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ColumnText16(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ColumnBlob(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_column_bytes", CallingConvention = CallingConvention.Cdecl)] + public static extern int ColumnBytes(IntPtr stmt, int index); + + public static string ColumnString(IntPtr stmt, int index) + { + return Marshal.PtrToStringUni(SQLite3.ColumnText16(stmt, index)); + } + + public static byte[] ColumnByteArray(IntPtr stmt, int index) + { + int length = ColumnBytes(stmt, index); + byte[] result = new byte[length]; + if (length > 0) + Marshal.Copy(ColumnBlob(stmt, index), result, 0, length); + return result; + } + + [DllImport("sqlite3", EntryPoint = "sqlite3_extended_errcode", CallingConvention = CallingConvention.Cdecl)] + public static extern ExtendedResult sqlite3_extended_errcode(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_libversion_number", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_libversion_number(); + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WinRT/SQLitePlatformWinRT.cs b/src/SQLite.Net.Platform.WinRT/SQLitePlatformWinRT.cs new file mode 100644 index 000000000..7872511a7 --- /dev/null +++ b/src/SQLite.Net.Platform.WinRT/SQLitePlatformWinRT.cs @@ -0,0 +1,26 @@ +using Windows.Storage; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.WinRT +{ + public class SQLitePlatformWinRT : ISQLitePlatform + { + public SQLitePlatformWinRT() + { + SQLiteApi = new SQLiteApiWinRT(); + VolatileService = new VolatileServiceWinRT(); + StopwatchFactory = new StopwatchFactoryWinRT(); + ReflectionService = new ReflectionServiceWinRT(); + } + + public string DatabaseRootDirectory + { + get { return ApplicationData.Current.LocalFolder.Path; } + } + + public ISQLiteApi SQLiteApi { get; private set; } + public IStopwatchFactory StopwatchFactory { get; private set; } + public IReflectionService ReflectionService { get; private set; } + public IVolatileService VolatileService { get; private set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WinRT/StopwatchFactoryWinRT.cs b/src/SQLite.Net.Platform.WinRT/StopwatchFactoryWinRT.cs new file mode 100644 index 000000000..1b583c9c8 --- /dev/null +++ b/src/SQLite.Net.Platform.WinRT/StopwatchFactoryWinRT.cs @@ -0,0 +1,43 @@ +using System.Diagnostics; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.WinRT +{ + public class StopwatchFactoryWinRT : IStopwatchFactory + { + public IStopwatch Create() + { + return new StopwatchWinRT(); + } + + private class StopwatchWinRT : IStopwatch + { + private readonly Stopwatch _stopWatch; + + public StopwatchWinRT() + { + _stopWatch = new Stopwatch(); + } + + public void Stop() + { + _stopWatch.Stop(); + } + + public void Reset() + { + _stopWatch.Reset(); + } + + public void Start() + { + _stopWatch.Start(); + } + + public long ElapsedMilliseconds + { + get { return _stopWatch.ElapsedMilliseconds; } + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WinRT/VolatileServiceWinRT.cs b/src/SQLite.Net.Platform.WinRT/VolatileServiceWinRT.cs new file mode 100644 index 000000000..896c4aeb2 --- /dev/null +++ b/src/SQLite.Net.Platform.WinRT/VolatileServiceWinRT.cs @@ -0,0 +1,13 @@ +using System.Threading; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.WinRT +{ + public class VolatileServiceWinRT : IVolatileService + { + public void Write(ref int transactionDepth, int depth) + { + Volatile.Write(ref transactionDepth, depth); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WindowsPhone8/Properties/AssemblyInfo.cs b/src/SQLite.Net.Platform.WindowsPhone8/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..fbef1141d --- /dev/null +++ b/src/SQLite.Net.Platform.WindowsPhone8/Properties/AssemblyInfo.cs @@ -0,0 +1,25 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("SQLite.Net.Platform.WindowsPhone8")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SQLite.Net.Platform.WindowsPhone8")] +[assembly: AssemblyCopyright("Copyright © Øystein Krog")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("741521f8-f9d8-40f4-a5d4-aed4e26841ed")] \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WindowsPhone8/ReflectionServiceWP8.cs b/src/SQLite.Net.Platform.WindowsPhone8/ReflectionServiceWP8.cs new file mode 100644 index 000000000..1ade84ad3 --- /dev/null +++ b/src/SQLite.Net.Platform.WindowsPhone8/ReflectionServiceWP8.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.WindowsPhone8 +{ + public class ReflectionServiceWP8 : IReflectionService + { + public IEnumerable GetPublicInstanceProperties(Type mappedType) + { + if (mappedType == null) + { + throw new ArgumentNullException("mappedType"); + } + return from p in mappedType.GetRuntimeProperties() + where + ((p.GetMethod != null && p.GetMethod.IsPublic) || (p.SetMethod != null && p.SetMethod.IsPublic) || + (p.GetMethod != null && p.GetMethod.IsStatic) || (p.SetMethod != null && p.SetMethod.IsStatic)) + select p; + } + + public object GetMemberValue(object obj, Expression expr, MemberInfo member) + { + if (member.MemberType == MemberTypes.Property) + { + var m = (PropertyInfo) member; + return m.GetValue(obj, null); + } + if (member.MemberType == MemberTypes.Field) + { + return Expression.Lambda(expr).Compile().DynamicInvoke(); + } + throw new NotSupportedException("MemberExpr: " + member.MemberType); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WindowsPhone8/SQLite.Net.Platform.WindowsPhone8.csproj b/src/SQLite.Net.Platform.WindowsPhone8/SQLite.Net.Platform.WindowsPhone8.csproj new file mode 100644 index 000000000..34d4b4561 --- /dev/null +++ b/src/SQLite.Net.Platform.WindowsPhone8/SQLite.Net.Platform.WindowsPhone8.csproj @@ -0,0 +1,119 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {741521F8-F9D8-40F4-A5D4-AED4E26841ED} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + SQLite.Net.Platform.WindowsPhone8 + SQLite.Net.Platform.WindowsPhone8 + WindowsPhone + v8.0 + $(TargetFrameworkVersion) + false + true + 11.0 + true + ..\..\ + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\x86\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\ARM\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + + + {ABF3D656-3D1C-45D1-B6FD-41B088E5A533} + SQLite.Net + + + ..\..\packages\sqlite-net-wp8.3.8.3\lib\windowsphone8\Sqlite.winmd + + + + + + + + + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WindowsPhone8/SQLiteApiWP8.cs b/src/SQLite.Net.Platform.WindowsPhone8/SQLiteApiWP8.cs new file mode 100644 index 000000000..2975da14b --- /dev/null +++ b/src/SQLite.Net.Platform.WindowsPhone8/SQLiteApiWP8.cs @@ -0,0 +1,283 @@ +using System; +using System.Text; +using Sqlite; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.WindowsPhone8 +{ + public class SQLiteApiWP8 : ISQLiteApi + { + public Result Open(byte[] filename, out IDbHandle db, int flags, IntPtr zVfs) + { + string dbFileName = Encoding.UTF8.GetString(filename, 0, filename.Length -1 ); + Database internalDbHandle = null; + var ret = (Result)Sqlite3.sqlite3_open_v2(dbFileName, out internalDbHandle, flags, ""); + db = new DbHandle(internalDbHandle); + return ret; + } + + public ExtendedResult ExtendedErrCode(IDbHandle db) + { + // not supported + return 0; +// var dbHandle = (DbHandle)db; +// return Sqlite3.sqlite3_extended_errcode(dbHandle.InternalDbHandle); + } + + public int LibVersionNumber() + { + // not supported + return 0; +// return Sqlite3.sqlite3_libversion_number(); + } + + public Result EnableLoadExtension(IDbHandle db, int onoff) + { + var dbHandle = (DbHandle)db; + return (Result)Sqlite3.sqlite3_enable_load_extension(dbHandle.InternalDbHandle, onoff); + } + + public Result Close(IDbHandle db) + { + var dbHandle = (DbHandle)db; + return (Result)Sqlite3.sqlite3_close(dbHandle.InternalDbHandle); + } + + public Result Initialize() + { + throw new NotSupportedException(); + } + public Result Shutdown() + { + throw new NotSupportedException(); + } + + public Result Config(ConfigOption option) + { + throw new NotSupportedException(); + } + + public Result BusyTimeout(IDbHandle db, int milliseconds) + { + var dbHandle = (DbHandle)db; + return (Result)Sqlite3.sqlite3_busy_timeout(dbHandle.InternalDbHandle, milliseconds); + } + + public int Changes(IDbHandle db) + { + var dbHandle = (DbHandle)db; + return Sqlite3.sqlite3_changes(dbHandle.InternalDbHandle); + } + + + public IDbStatement Prepare2(IDbHandle db, string query) + { + var dbHandle = (DbHandle)db; + var stmt = default(Statement); + + int r = Sqlite3.sqlite3_prepare_v2(dbHandle.InternalDbHandle, query, out stmt); + + if (r != 0) + { + throw SQLiteException.New((Result)r, GetErrmsg(db)); + } + return new DbStatement(stmt); + } + + public Result Step(IDbStatement stmt) + { + var dbStatement = (DbStatement)stmt; + return (Result)Sqlite3.sqlite3_step(dbStatement.InternalStmt); + } + + public Result Reset(IDbStatement stmt) + { + var dbStatement = (DbStatement)stmt; + return (Result)Sqlite3.sqlite3_reset(dbStatement.InternalStmt); + } + + public Result Finalize(IDbStatement stmt) + { + var dbStatement = (DbStatement)stmt; + Statement internalStmt = dbStatement.InternalStmt; + return (Result)Sqlite3.sqlite3_finalize(internalStmt); + } + + public long LastInsertRowid(IDbHandle db) + { + var dbHandle = (DbHandle)db; + return Sqlite3.sqlite3_last_insert_rowid(dbHandle.InternalDbHandle); + } + + public string Errmsg16(IDbHandle db) + { + var dbHandle = (DbHandle)db; + return Sqlite3.sqlite3_errmsg(dbHandle.InternalDbHandle); + } + + public int BindParameterIndex(IDbStatement stmt, string name) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_bind_parameter_index(dbStatement.InternalStmt, name); + } + + public int BindNull(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_bind_null(dbStatement.InternalStmt, index); + } + + public int BindInt(IDbStatement stmt, int index, int val) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_bind_int(dbStatement.InternalStmt, index, val); + } + + public int BindInt64(IDbStatement stmt, int index, long val) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_bind_int64(dbStatement.InternalStmt, index, val); + } + + public int BindDouble(IDbStatement stmt, int index, double val) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_bind_double(dbStatement.InternalStmt, index, val); + } + + public int BindText16(IDbStatement stmt, int index, string val, int n, IntPtr free) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_bind_text(dbStatement.InternalStmt, index, val, n); + } + + public int BindBlob(IDbStatement stmt, int index, byte[] val, int n, IntPtr free) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_bind_blob(dbStatement.InternalStmt, index, val, n); + } + + public int ColumnCount(IDbStatement stmt) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_count(dbStatement.InternalStmt); + } + + public string ColumnName16(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_name(dbStatement.InternalStmt, index); + } + + public ColType ColumnType(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return (ColType)Sqlite3.sqlite3_column_type(dbStatement.InternalStmt, index); + } + + public int ColumnInt(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_int(dbStatement.InternalStmt, index); + } + + public long ColumnInt64(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_int64(dbStatement.InternalStmt, index); + } + + public double ColumnDouble(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_double(dbStatement.InternalStmt, index); + } + + public int ColumnBytes(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_bytes(dbStatement.InternalStmt, index); + } + + public byte[] ColumnByteArray(IDbStatement stmt, int index) + { + return ColumnBlob(stmt, index); + } + + public string ColumnText16(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_text(dbStatement.InternalStmt, index); + } + + public byte[] ColumnBlob(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_blob(dbStatement.InternalStmt, index); + } + + public Result Open(string filename, out IDbHandle db) + { + Database internalDbHandle = null; + var ret = (Result)Sqlite3.sqlite3_open(filename, out internalDbHandle); + db = new DbHandle(internalDbHandle); + return ret; + } + + public string GetErrmsg(IDbHandle db) + { + var dbHandle = (DbHandle)db; + return Sqlite3.sqlite3_errmsg(dbHandle.InternalDbHandle); + } + + public string ColumnString(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_text(dbStatement.InternalStmt, index); + } + + public string ColumnName(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_name(dbStatement.InternalStmt, index); + } + + public string ColumnText(IDbStatement stmt, int index) + { + var dbStatement = (DbStatement)stmt; + return Sqlite3.sqlite3_column_text(dbStatement.InternalStmt, index); + } + + private struct DbHandle : IDbHandle + { + public DbHandle(Database internalDbHandle) + : this() + { + InternalDbHandle = internalDbHandle; + } + + public Database InternalDbHandle { get; set; } + + public bool Equals(IDbHandle other) + { + return other is DbHandle && InternalDbHandle == ((DbHandle)other).InternalDbHandle; + } + } + + private struct DbStatement : IDbStatement + { + public DbStatement(Statement internalStmt) + : this() + { + InternalStmt = internalStmt; + } + + internal Statement InternalStmt { get; set; } + + public bool Equals(IDbStatement other) + { + return (other is DbStatement) && ((DbStatement)other).InternalStmt == InternalStmt; + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WindowsPhone8/SQLitePlatformWP8.cs b/src/SQLite.Net.Platform.WindowsPhone8/SQLitePlatformWP8.cs new file mode 100644 index 000000000..268a0c57a --- /dev/null +++ b/src/SQLite.Net.Platform.WindowsPhone8/SQLitePlatformWP8.cs @@ -0,0 +1,24 @@ +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.WindowsPhone8 +{ + public class SQLitePlatformWP8 : ISQLitePlatform + { + public SQLitePlatformWP8() + { + var api = new SQLiteApiWP8(); + +// api.SetDirectory(/*temp directory type*/2, Windows.Storage.ApplicationData.Current.TemporaryFolder.Path); + + SQLiteApi = api; + VolatileService = new VolatileServiceWP8(); + ReflectionService = new ReflectionServiceWP8(); + StopwatchFactory = new StopwatchFactoryWP8(); + } + + public ISQLiteApi SQLiteApi { get; private set; } + public IStopwatchFactory StopwatchFactory { get; private set; } + public IReflectionService ReflectionService { get; private set; } + public IVolatileService VolatileService { get; private set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WindowsPhone8/StopwatchFactoryWP8.cs b/src/SQLite.Net.Platform.WindowsPhone8/StopwatchFactoryWP8.cs new file mode 100644 index 000000000..06a18cbc4 --- /dev/null +++ b/src/SQLite.Net.Platform.WindowsPhone8/StopwatchFactoryWP8.cs @@ -0,0 +1,43 @@ +using System.Diagnostics; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.WindowsPhone8 +{ + public class StopwatchFactoryWP8 : IStopwatchFactory + { + public IStopwatch Create() + { + return new StopwatchWP8(); + } + + private class StopwatchWP8 : IStopwatch + { + private readonly Stopwatch _stopWatch; + + public StopwatchWP8() + { + _stopWatch = new Stopwatch(); + } + + public void Stop() + { + _stopWatch.Stop(); + } + + public void Reset() + { + _stopWatch.Reset(); + } + + public void Start() + { + _stopWatch.Start(); + } + + public long ElapsedMilliseconds + { + get { return _stopWatch.ElapsedMilliseconds; } + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WindowsPhone8/VolatileServiceWP8.cs b/src/SQLite.Net.Platform.WindowsPhone8/VolatileServiceWP8.cs new file mode 100644 index 000000000..c47755249 --- /dev/null +++ b/src/SQLite.Net.Platform.WindowsPhone8/VolatileServiceWP8.cs @@ -0,0 +1,13 @@ +using System.Threading; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.WindowsPhone8 +{ + public class VolatileServiceWP8 : IVolatileService + { + public void Write(ref int transactionDepth, int depth) + { + Volatile.Write(ref transactionDepth, depth); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WindowsPhone8/packages.config b/src/SQLite.Net.Platform.WindowsPhone8/packages.config new file mode 100644 index 000000000..dff1dbcc9 --- /dev/null +++ b/src/SQLite.Net.Platform.WindowsPhone8/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WindowsPhoneApp81/Properties/AssemblyInfo.cs b/src/SQLite.Net.Platform.WindowsPhoneApp81/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..070648cd3 --- /dev/null +++ b/src/SQLite.Net.Platform.WindowsPhoneApp81/Properties/AssemblyInfo.cs @@ -0,0 +1,14 @@ +using System.Reflection; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("SQLite.Net.Platform.WindowsPhoneApp81")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Øystein Krog")] +[assembly: AssemblyProduct("SQLite.Net.Platform.WinRT")] +[assembly: AssemblyCopyright("Copyright © Øystein Krog")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/SQLite.Net.Platform.WindowsPhoneApp81/SQLite.Net.Platform.WindowsPhoneApp81.csproj b/src/SQLite.Net.Platform.WindowsPhoneApp81/SQLite.Net.Platform.WindowsPhoneApp81.csproj new file mode 100644 index 000000000..19c9ce53e --- /dev/null +++ b/src/SQLite.Net.Platform.WindowsPhoneApp81/SQLite.Net.Platform.WindowsPhoneApp81.csproj @@ -0,0 +1,123 @@ + + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {38AF8105-65B6-4A14-A258-1137D9E40EF1} + Library + Properties + SQLite.Net.Platform.WindowsPhoneApp81 + SQLite.Net.Platform.WindowsPhoneApp81 + en-US + 8.1 + 12 + 512 + {76F1466A-8B6D-4E39-A767-685A06062A39};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + true + full + false + bin\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;NETFX_CORE;WINDOWS_PHONE_APP + prompt + 4 + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_PHONE_APP + true + ;2008 + pdbonly + ARM + false + prompt + true + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_PHONE_APP + true + ;2008 + pdbonly + x86 + false + prompt + true + + + + + {4971d437-0694-4297-a8cc-146ce08c3bd9} + SQLite.Net + + + + + Properties\GlobalAssemblyInfo.cs + + + ReflectionServiceWinRT.cs + + + SQLiteApiWinRT.cs + + + SQLitePlatformWinRT.cs + + + StopwatchFactoryWinRT.cs + + + VolatileServiceWinRT.cs + + + + + 12.0 + + + WindowsPhoneApp + + + + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/Properties/AssemblyInfo.cs b/src/SQLite.Net.Platform.XamarinAndroid/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..00b42c984 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/Properties/AssemblyInfo.cs @@ -0,0 +1,18 @@ +using System.Reflection; +using System.Runtime.InteropServices; +using Android; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("SQLite.Net.Platform.XamarinAndroid")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Øystein Krog")] +[assembly: AssemblyProduct("SQLite.Net.Platform.XamarinAndroid")] +[assembly: AssemblyCopyright("Copyright © Øystein Krog")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] diff --git a/src/SQLite.Net.Platform.XamarinAndroid/ReflectionServiceAndroid.cs b/src/SQLite.Net.Platform.XamarinAndroid/ReflectionServiceAndroid.cs new file mode 100644 index 000000000..f91597d17 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/ReflectionServiceAndroid.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinAndroid +{ + public class ReflectionServiceAndroid : IReflectionService + { + public IEnumerable GetPublicInstanceProperties(Type mappedType) + { + return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); + } + + public object GetMemberValue(object obj, Expression expr, MemberInfo member) + { + if (member.MemberType == MemberTypes.Property) + { + var m = (PropertyInfo) member; + return m.GetValue(obj, null); + } + if (member.MemberType == MemberTypes.Field) + { + var m = (FieldInfo) member; + return m.GetValue(obj); + } + throw new NotSupportedException("MemberExpr: " + member.MemberType); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/Resources/AboutResources.txt b/src/SQLite.Net.Platform.XamarinAndroid/Resources/AboutResources.txt new file mode 100644 index 000000000..194ae28a5 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/Resources/AboutResources.txt @@ -0,0 +1,50 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.xml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable-hdpi/ + icon.png + + drawable-ldpi/ + icon.png + + drawable-mdpi/ + icon.png + + layout/ + main.xml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called +"Resource" that contains the tokens for each one of the resources included. For example, +for the above Resources layout, this is what the Resource class would expose: + +public class Resource { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main +to reference the layout/main.xml file, or Resource.strings.first_string to reference the first +string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/Resources/Resource.Designer.cs b/src/SQLite.Net.Platform.XamarinAndroid/Resources/Resource.Designer.cs new file mode 100644 index 000000000..eb55d1d4f --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/Resources/Resource.Designer.cs @@ -0,0 +1,60 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("SQLite.Net.Platform.XamarinAndroid.Resource", IsApplication=false)] + +namespace SQLite.Net.Platform.XamarinAndroid +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f020001 + public static int ApplicationName = 2130837505; + + // aapt resource value: 0x7f020000 + public static int Hello = 2130837504; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/src/SQLite.Net.Platform.XamarinAndroid/Resources/Values/Strings.xml b/src/SQLite.Net.Platform.XamarinAndroid/Resources/Values/Strings.xml new file mode 100644 index 000000000..360d864a5 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/Resources/Values/Strings.xml @@ -0,0 +1,6 @@ + + + + Hello World, Click Me! + $projectname$ + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/SQLite.Net.Platform.XamarinAndroid.csproj b/src/SQLite.Net.Platform.XamarinAndroid/SQLite.Net.Platform.XamarinAndroid.csproj new file mode 100644 index 000000000..e4b5b05ec --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/SQLite.Net.Platform.XamarinAndroid.csproj @@ -0,0 +1,76 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {219700F0-5444-4250-87D6-0551B39CA402} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Properties + SQLite.Net.Platform.XamarinAndroid + SQLite.Net.Platform.XamarinAndroid + 512 + Resources\Resource.Designer.cs + Off + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + + + + + + + + {ABF3D656-3D1C-45D1-B6FD-41B088E5A533} + SQLite.Net + + + + + + + + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/SQLiteApiAndroid.cs b/src/SQLite.Net.Platform.XamarinAndroid/SQLiteApiAndroid.cs new file mode 100644 index 000000000..d139ee14f --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/SQLiteApiAndroid.cs @@ -0,0 +1,244 @@ +using System; +using System.Runtime.InteropServices; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinAndroid +{ + public class SQLiteApiAndroid : ISQLiteApi + { + public Result Open(byte[] filename, out IDbHandle db, int flags, IntPtr zvfs) + { + IntPtr dbPtr; + Result r = SQLiteApiAndroidInternal.sqlite3_open_v2(filename, out dbPtr, flags, zvfs); + db = new DbHandle(dbPtr); + return r; + } + + public ExtendedResult ExtendedErrCode(IDbHandle db) + { + var internalDbHandle = (DbHandle)db; + return SQLiteApiAndroidInternal.sqlite3_extended_errcode(internalDbHandle.DbPtr); + } + + public int LibVersionNumber() + { + return SQLiteApiAndroidInternal.sqlite3_libversion_number(); + } + + public Result EnableLoadExtension(IDbHandle db, int onoff) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiAndroidInternal.sqlite3_enable_load_extension(internalDbHandle.DbPtr, onoff); + } + + public Result Close(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiAndroidInternal.sqlite3_close(internalDbHandle.DbPtr); + } + + public Result Initialize() + { + return SQLiteApiAndroidInternal.sqlite3_initialize(); + } + public Result Shutdown() + { + return SQLiteApiAndroidInternal.sqlite3_shutdown(); + } + + public Result Config(ConfigOption option) + { + return SQLiteApiAndroidInternal.sqlite3_config(option); + } + + public Result BusyTimeout(IDbHandle db, int milliseconds) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiAndroidInternal.sqlite3_busy_timeout(internalDbHandle.DbPtr, milliseconds); + } + + public int Changes(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiAndroidInternal.sqlite3_changes(internalDbHandle.DbPtr); + } + + public IDbStatement Prepare2(IDbHandle db, string query) + { + var internalDbHandle = (DbHandle) db; + IntPtr stmt; + Result r = SQLiteApiAndroidInternal.sqlite3_prepare_v2(internalDbHandle.DbPtr, query, query.Length, out stmt, IntPtr.Zero); + if (r != Result.OK) + { + throw SQLiteException.New(r, Errmsg16(internalDbHandle)); + } + return new DbStatement(stmt); + } + + public Result Step(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_step(internalStmt.StmtPtr); + } + + public Result Reset(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_reset(internalStmt.StmtPtr); + } + + public Result Finalize(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_finalize(internalStmt.StmtPtr); + } + + public long LastInsertRowid(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiAndroidInternal.sqlite3_last_insert_rowid(internalDbHandle.DbPtr); + } + + public string Errmsg16(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return Marshal.PtrToStringUni(SQLiteApiAndroidInternal.sqlite3_errmsg16(internalDbHandle.DbPtr)); + } + + public int BindParameterIndex(IDbStatement stmt, string name) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_bind_parameter_index(internalStmt.StmtPtr, name); + } + + public int BindNull(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_bind_null(internalStmt.StmtPtr, index); + } + + public int BindInt(IDbStatement stmt, int index, int val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_bind_int(internalStmt.StmtPtr, index, val); + } + + public int BindInt64(IDbStatement stmt, int index, long val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_bind_int64(internalStmt.StmtPtr, index, val); + } + + public int BindDouble(IDbStatement stmt, int index, double val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_bind_double(internalStmt.StmtPtr, index, val); + } + + public int BindText16(IDbStatement stmt, int index, string val, int n, IntPtr free) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_bind_text16(internalStmt.StmtPtr, index, val, n, free); + } + + public int BindBlob(IDbStatement stmt, int index, byte[] val, int n, IntPtr free) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_bind_blob(internalStmt.StmtPtr, index, val, n, free); + } + + public int ColumnCount(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_column_count(internalStmt.StmtPtr); + } + + public string ColumnName16(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.ColumnName16(internalStmt.StmtPtr, index); + } + + public ColType ColumnType(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_column_type(internalStmt.StmtPtr, index); + } + + public int ColumnInt(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_column_int(internalStmt.StmtPtr, index); + } + + public long ColumnInt64(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_column_int64(internalStmt.StmtPtr, index); + } + + public double ColumnDouble(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_column_double(internalStmt.StmtPtr, index); + } + + public string ColumnText16(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return Marshal.PtrToStringUni(SQLiteApiAndroidInternal.sqlite3_column_text16(internalStmt.StmtPtr, index)); + } + + public byte[] ColumnBlob(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.ColumnBlob(internalStmt.StmtPtr, index); + } + + public int ColumnBytes(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.sqlite3_column_bytes(internalStmt.StmtPtr, index); + } + + public byte[] ColumnByteArray(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiAndroidInternal.ColumnByteArray(internalStmt.StmtPtr, index); + } + + private struct DbHandle : IDbHandle + { + public DbHandle(IntPtr dbPtr) + : this() + { + DbPtr = dbPtr; + } + + internal IntPtr DbPtr { get; set; } + + public bool Equals(IDbHandle other) + { + return other is DbHandle && DbPtr == ((DbHandle) other).DbPtr; + } + } + + private struct DbStatement : IDbStatement + { + public DbStatement(IntPtr stmtPtr) + : this() + { + StmtPtr = stmtPtr; + } + + internal IntPtr StmtPtr { get; set; } + + public bool Equals(IDbStatement other) + { + return other is DbStatement && StmtPtr == ((DbStatement) other).StmtPtr; + } + } + + + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/SQLiteApiAndroidInternal.cs b/src/SQLite.Net.Platform.XamarinAndroid/SQLiteApiAndroidInternal.cs new file mode 100644 index 000000000..983be0d6c --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/SQLiteApiAndroidInternal.cs @@ -0,0 +1,160 @@ +using System; +using System.Runtime.InteropServices; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinAndroid +{ + internal static class SQLiteApiAndroidInternal + { + private const string DllName = "sqlite3"; + + [DllImport(DllName, EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern byte[] ColumnBlob(IntPtr stmt, int index); + + public static byte[] ColumnByteArray(IntPtr stmt, int index) + { + int length = sqlite3_column_bytes(stmt, index); + var result = new byte[length]; + if (length > 0) + { + Marshal.Copy(sqlite3_column_blob(stmt, index), result, 0, length); + } + return result; + } + + public static string ColumnName16(IntPtr stmt, int index) + { + return Marshal.PtrToStringUni(sqlite3_column_name16(stmt, index)); + } + + [DllImport(DllName, EntryPoint = "sqlite3_bind_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_blob(IntPtr stmt, int index, byte[] val, int n, IntPtr free); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_double", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_double(IntPtr stmt, int index, double val); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_int(IntPtr stmt, int index, int val); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_int64", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_int64(IntPtr stmt, int index, long val); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_null", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_null(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_parameter_index", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_parameter_index(IntPtr stmt, [MarshalAs(UnmanagedType.LPStr)] string name); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_text16", CallingConvention = CallingConvention.Cdecl, + CharSet = CharSet.Unicode)] + public static extern int sqlite3_bind_text16(IntPtr stmt, + int index, + [MarshalAs(UnmanagedType.LPWStr)] string val, + int n, + IntPtr free); + + [DllImport(DllName, EntryPoint = "sqlite3_busy_timeout", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_busy_timeout(IntPtr db, int milliseconds); + + [DllImport(DllName, EntryPoint = "sqlite3_changes", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_changes(IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_close", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_close(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_initialize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_initialize(); + + [DllImport("sqlite3", EntryPoint = "sqlite3_shutdown", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_shutdown(); + + [DllImport(DllName, EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_column_blob(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_bytes", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_bytes(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_count", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_count(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_column_double", CallingConvention = CallingConvention.Cdecl)] + public static extern double sqlite3_column_double(IntPtr stmt, int index); + + // [DllImport(DllName, EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + // private extern IntPtr ColumnNameInternal(IntPtr stmt, int index); + + // [DllImport(DllName, EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + // public string ColumnName(IntPtr stmt, int index) + // { + // return ColumnNameInternal(stmt, index); + // } + + [DllImport(DllName, EntryPoint = "sqlite3_column_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_int(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_int64", CallingConvention = CallingConvention.Cdecl)] + public static extern long sqlite3_column_int64(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_text16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_column_text16(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_type", CallingConvention = CallingConvention.Cdecl)] + public static extern ColType sqlite3_column_type(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_config", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_config(ConfigOption option); + + [DllImport(DllName, EntryPoint = "sqlite3_enable_load_extension", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_enable_load_extension(IntPtr db, int onoff); + + [DllImport(DllName, EntryPoint = "sqlite3_errmsg16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_errmsg16(IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_finalize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_finalize(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_last_insert_rowid", CallingConvention = CallingConvention.Cdecl)] + public static extern long sqlite3_last_insert_rowid(IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_open", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport(DllName, EntryPoint = "sqlite3_open16", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open16([MarshalAs(UnmanagedType.LPWStr)] string filename, out IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open_v2(byte[] filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport(DllName, EntryPoint = "sqlite3_prepare_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_prepare_v2(IntPtr db, + [MarshalAs(UnmanagedType.LPStr)] string sql, + int numBytes, + out IntPtr stmt, + IntPtr pzTail); + + [DllImport(DllName, EntryPoint = "sqlite3_reset", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_reset(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_step", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_step(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_win32_set_directory", CallingConvention = CallingConvention.Cdecl, + CharSet = CharSet.Unicode)] + public static extern int sqlite3_win32_set_directory(uint directoryType, string directoryPath); + + [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern IntPtr LoadLibrary(string lpFileName); + + [DllImport(DllName, EntryPoint = "sqlite3_column_name16", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr sqlite3_column_name16(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_extended_errcode", CallingConvention = CallingConvention.Cdecl)] + public static extern ExtendedResult sqlite3_extended_errcode(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_libversion_number", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_libversion_number(); + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/SQLitePlatformAndroid.cs b/src/SQLite.Net.Platform.XamarinAndroid/SQLitePlatformAndroid.cs new file mode 100644 index 000000000..ed6831b03 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/SQLitePlatformAndroid.cs @@ -0,0 +1,20 @@ +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinAndroid +{ + public class SQLitePlatformAndroid : ISQLitePlatform + { + public SQLitePlatformAndroid() + { + SQLiteApi = new SQLiteApiAndroid(); + StopwatchFactory = new StopwatchFactoryAndroid(); + ReflectionService = new ReflectionServiceAndroid(); + VolatileService = new VolatileServiceAndroid(); + } + + public ISQLiteApi SQLiteApi { get; private set; } + public IStopwatchFactory StopwatchFactory { get; private set; } + public IReflectionService ReflectionService { get; private set; } + public IVolatileService VolatileService { get; private set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/StopwatchFactoryAndroid.cs b/src/SQLite.Net.Platform.XamarinAndroid/StopwatchFactoryAndroid.cs new file mode 100644 index 000000000..8b9fc6457 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/StopwatchFactoryAndroid.cs @@ -0,0 +1,43 @@ +using System.Diagnostics; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinAndroid +{ + public class StopwatchFactoryAndroid : IStopwatchFactory + { + public IStopwatch Create() + { + return new StopwatchAndroid(); + } + + private class StopwatchAndroid : IStopwatch + { + private readonly Stopwatch _stopWatch; + + public StopwatchAndroid() + { + _stopWatch = new Stopwatch(); + } + + public void Stop() + { + _stopWatch.Stop(); + } + + public void Reset() + { + _stopWatch.Reset(); + } + + public void Start() + { + _stopWatch.Start(); + } + + public long ElapsedMilliseconds + { + get { return _stopWatch.ElapsedMilliseconds; } + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/VolatileServiceAndroid.cs b/src/SQLite.Net.Platform.XamarinAndroid/VolatileServiceAndroid.cs new file mode 100644 index 000000000..4fa6fefff --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinAndroid/VolatileServiceAndroid.cs @@ -0,0 +1,13 @@ +using System.Threading; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinAndroid +{ + public class VolatileServiceAndroid : IVolatileService + { + public void Write(ref int transactionDepth, int depth) + { + Volatile.Write(ref transactionDepth, depth); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS.Unified/Properties/AssemblyInfo.cs b/src/SQLite.Net.Platform.XamarinIOS.Unified/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..5839546f7 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS.Unified/Properties/AssemblyInfo.cs @@ -0,0 +1,28 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("SQLite.Net.Platform.XamarinIOS.Unified")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Leon Lucardie")] +[assembly: AssemblyProduct("SQLite.Net.Platform.XamarinIOS.Unified")] +[assembly: AssemblyCopyright("Copyright ©Øystein Krog 2013-2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/src/SQLite.Net.Platform.XamarinIOS.Unified/ReflectionServiceIOS.cs b/src/SQLite.Net.Platform.XamarinIOS.Unified/ReflectionServiceIOS.cs new file mode 100644 index 000000000..ec69f0ef1 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS.Unified/ReflectionServiceIOS.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + public class ReflectionServiceIOS : IReflectionService + { + public IEnumerable GetPublicInstanceProperties(Type mappedType) + { + return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); + } + + public object GetMemberValue(object obj, Expression expr, MemberInfo member) + { + if (member.MemberType == MemberTypes.Property) + { + var m = (PropertyInfo) member; + return m.GetValue(obj, null); + } + if (member.MemberType == MemberTypes.Field) + { + var m = (FieldInfo) member; + return m.GetValue(obj); + } + throw new NotSupportedException("MemberExpr: " + member.MemberType); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLite.Net.Platform.XamarinIOS.Unified.csproj b/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLite.Net.Platform.XamarinIOS.Unified.csproj new file mode 100644 index 000000000..b4a74863d --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLite.Net.Platform.XamarinIOS.Unified.csproj @@ -0,0 +1,56 @@ + + + + Debug + AnyCPU + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {3173703F-8B1F-4772-9AE3-44913F413FB1} + Library + SQLite.Net.Platform.XamarinIOS.Unified + Resources + SQLite.Net.Platform.XamarinIOS.Unified + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + full + true + bin\Release + prompt + 4 + false + + + + + + + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLiteApiIOS.cs b/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLiteApiIOS.cs new file mode 100644 index 000000000..b9b189a13 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLiteApiIOS.cs @@ -0,0 +1,242 @@ +using System; +using System.Runtime.InteropServices; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + public class SQLiteApiIOS : ISQLiteApi + { + public Result Open(byte[] filename, out IDbHandle db, int flags, IntPtr zvfs) + { + IntPtr dbPtr; + Result r = SQLiteApiIOSInternal.sqlite3_open_v2(filename, out dbPtr, flags, zvfs); + db = new DbHandle(dbPtr); + return r; + } + + public ExtendedResult ExtendedErrCode(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_extended_errcode(internalDbHandle.DbPtr); + } + + public int LibVersionNumber() + { + return SQLiteApiIOSInternal.sqlite3_libversion_number(); + } + + public Result EnableLoadExtension(IDbHandle db, int onoff) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_enable_load_extension(internalDbHandle.DbPtr, onoff); + } + + public Result Close(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_close(internalDbHandle.DbPtr); + } + + public Result Initialize() + { + return SQLiteApiIOSInternal.sqlite3_initialize(); + } + public Result Shutdown() + { + return SQLiteApiIOSInternal.sqlite3_shutdown(); + } + + public Result Config(ConfigOption option) + { + return SQLiteApiIOSInternal.sqlite3_config(option); + } + + public Result BusyTimeout(IDbHandle db, int milliseconds) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_busy_timeout(internalDbHandle.DbPtr, milliseconds); + } + + public int Changes(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_changes(internalDbHandle.DbPtr); + } + + public IDbStatement Prepare2(IDbHandle db, string query) + { + var internalDbHandle = (DbHandle) db; + IntPtr stmt; + Result r = SQLiteApiIOSInternal.sqlite3_prepare_v2(internalDbHandle.DbPtr, query, query.Length, out stmt, IntPtr.Zero); + if (r != Result.OK) + { + throw SQLiteException.New(r, Errmsg16(internalDbHandle)); + } + return new DbStatement(stmt); + } + + public Result Step(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_step(internalStmt.StmtPtr); + } + + public Result Reset(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_reset(internalStmt.StmtPtr); + } + + public Result Finalize(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_finalize(internalStmt.StmtPtr); + } + + public long LastInsertRowid(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_last_insert_rowid(internalDbHandle.DbPtr); + } + + public string Errmsg16(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return Marshal.PtrToStringUni(SQLiteApiIOSInternal.sqlite3_errmsg16(internalDbHandle.DbPtr)); + } + + public int BindParameterIndex(IDbStatement stmt, string name) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_parameter_index(internalStmt.StmtPtr, name); + } + + public int BindNull(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_null(internalStmt.StmtPtr, index); + } + + public int BindInt(IDbStatement stmt, int index, int val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_int(internalStmt.StmtPtr, index, val); + } + + public int BindInt64(IDbStatement stmt, int index, long val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_int64(internalStmt.StmtPtr, index, val); + } + + public int BindDouble(IDbStatement stmt, int index, double val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_double(internalStmt.StmtPtr, index, val); + } + + public int BindText16(IDbStatement stmt, int index, string val, int n, IntPtr free) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_text16(internalStmt.StmtPtr, index, val, n, free); + } + + public int BindBlob(IDbStatement stmt, int index, byte[] val, int n, IntPtr free) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_blob(internalStmt.StmtPtr, index, val, n, free); + } + + public int ColumnCount(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_count(internalStmt.StmtPtr); + } + + public string ColumnName16(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.ColumnName16(internalStmt.StmtPtr, index); + } + + public ColType ColumnType(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_type(internalStmt.StmtPtr, index); + } + + public int ColumnInt(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_int(internalStmt.StmtPtr, index); + } + + public long ColumnInt64(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_int64(internalStmt.StmtPtr, index); + } + + public double ColumnDouble(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_double(internalStmt.StmtPtr, index); + } + + public string ColumnText16(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return Marshal.PtrToStringUni(SQLiteApiIOSInternal.sqlite3_column_text16(internalStmt.StmtPtr, index)); + } + + public byte[] ColumnBlob(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.ColumnBlob(internalStmt.StmtPtr, index); + } + + public int ColumnBytes(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_bytes(internalStmt.StmtPtr, index); + } + + public byte[] ColumnByteArray(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.ColumnByteArray(internalStmt.StmtPtr, index); + } + + private struct DbHandle : IDbHandle + { + public DbHandle(IntPtr dbPtr) + : this() + { + DbPtr = dbPtr; + } + + internal IntPtr DbPtr { get; set; } + + public bool Equals(IDbHandle other) + { + return other is DbHandle && DbPtr == ((DbHandle) other).DbPtr; + } + } + + private struct DbStatement : IDbStatement + { + public DbStatement(IntPtr stmtPtr) + : this() + { + StmtPtr = stmtPtr; + } + + internal IntPtr StmtPtr { get; set; } + + public bool Equals(IDbStatement other) + { + return other is DbStatement && StmtPtr == ((DbStatement) other).StmtPtr; + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLiteApiIOSInternal.cs b/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLiteApiIOSInternal.cs new file mode 100644 index 000000000..222b2798a --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLiteApiIOSInternal.cs @@ -0,0 +1,160 @@ +using System; +using System.Runtime.InteropServices; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + internal static class SQLiteApiIOSInternal + { + private const string DllName = "sqlite3"; + + [DllImport(DllName, EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern byte[] ColumnBlob(IntPtr stmt, int index); + + public static byte[] ColumnByteArray(IntPtr stmt, int index) + { + int length = sqlite3_column_bytes(stmt, index); + var result = new byte[length]; + if (length > 0) + { + Marshal.Copy(sqlite3_column_blob(stmt, index), result, 0, length); + } + return result; + } + + public static string ColumnName16(IntPtr stmt, int index) + { + return Marshal.PtrToStringUni(sqlite3_column_name16(stmt, index)); + } + + [DllImport(DllName, EntryPoint = "sqlite3_bind_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_blob(IntPtr stmt, int index, byte[] val, int n, IntPtr free); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_double", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_double(IntPtr stmt, int index, double val); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_int(IntPtr stmt, int index, int val); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_int64", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_int64(IntPtr stmt, int index, long val); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_null", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_null(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_parameter_index", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_parameter_index(IntPtr stmt, [MarshalAs(UnmanagedType.LPStr)] string name); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_text16", CallingConvention = CallingConvention.Cdecl, + CharSet = CharSet.Unicode)] + public static extern int sqlite3_bind_text16(IntPtr stmt, + int index, + [MarshalAs(UnmanagedType.LPWStr)] string val, + int n, + IntPtr free); + + [DllImport(DllName, EntryPoint = "sqlite3_busy_timeout", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_busy_timeout(IntPtr db, int milliseconds); + + [DllImport(DllName, EntryPoint = "sqlite3_changes", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_changes(IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_close", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_close(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_initialize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_initialize(); + + [DllImport("sqlite3", EntryPoint = "sqlite3_shutdown", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_shutdown(); + + [DllImport(DllName, EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_column_blob(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_bytes", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_bytes(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_count", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_count(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_column_double", CallingConvention = CallingConvention.Cdecl)] + public static extern double sqlite3_column_double(IntPtr stmt, int index); + + // [DllImport(DllName, EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + // private extern IntPtr ColumnNameInternal(IntPtr stmt, int index); + + // [DllImport(DllName, EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + // public string ColumnName(IntPtr stmt, int index) + // { + // return ColumnNameInternal(stmt, index); + // } + + [DllImport(DllName, EntryPoint = "sqlite3_column_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_int(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_int64", CallingConvention = CallingConvention.Cdecl)] + public static extern long sqlite3_column_int64(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_text16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_column_text16(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_type", CallingConvention = CallingConvention.Cdecl)] + public static extern ColType sqlite3_column_type(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_config", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_config(ConfigOption option); + + [DllImport(DllName, EntryPoint = "sqlite3_enable_load_extension", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_enable_load_extension(IntPtr db, int onoff); + + [DllImport(DllName, EntryPoint = "sqlite3_errmsg16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_errmsg16(IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_finalize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_finalize(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_last_insert_rowid", CallingConvention = CallingConvention.Cdecl)] + public static extern long sqlite3_last_insert_rowid(IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_open", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport(DllName, EntryPoint = "sqlite3_open16", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open16([MarshalAs(UnmanagedType.LPWStr)] string filename, out IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open_v2(byte[] filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport(DllName, EntryPoint = "sqlite3_prepare_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_prepare_v2(IntPtr db, + [MarshalAs(UnmanagedType.LPStr)] string sql, + int numBytes, + out IntPtr stmt, + IntPtr pzTail); + + [DllImport(DllName, EntryPoint = "sqlite3_reset", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_reset(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_step", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_step(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_win32_set_directory", CallingConvention = CallingConvention.Cdecl, + CharSet = CharSet.Unicode)] + public static extern int sqlite3_win32_set_directory(uint directoryType, string directoryPath); + + [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern IntPtr LoadLibrary(string lpFileName); + + [DllImport(DllName, EntryPoint = "sqlite3_column_name16", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr sqlite3_column_name16(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_extended_errcode", CallingConvention = CallingConvention.Cdecl)] + public static extern ExtendedResult sqlite3_extended_errcode(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_libversion_number", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_libversion_number(); + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLitePlatformIOS.cs b/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLitePlatformIOS.cs new file mode 100644 index 000000000..1a39432e7 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLitePlatformIOS.cs @@ -0,0 +1,20 @@ +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + public class SQLitePlatformIOS : ISQLitePlatform + { + public SQLitePlatformIOS() + { + SQLiteApi = new SQLiteApiIOS(); + StopwatchFactory = new StopwatchFactoryIOS(); + ReflectionService = new ReflectionServiceIOS(); + VolatileService = new VolatileServiceIOS(); + } + + public ISQLiteApi SQLiteApi { get; private set; } + public IStopwatchFactory StopwatchFactory { get; private set; } + public IReflectionService ReflectionService { get; private set; } + public IVolatileService VolatileService { get; private set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS.Unified/StopwatchFactoryIOS.cs b/src/SQLite.Net.Platform.XamarinIOS.Unified/StopwatchFactoryIOS.cs new file mode 100644 index 000000000..9d5905f20 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS.Unified/StopwatchFactoryIOS.cs @@ -0,0 +1,43 @@ +using System.Diagnostics; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + public class StopwatchFactoryIOS : IStopwatchFactory + { + public IStopwatch Create() + { + return new StopwatchIOS(); + } + + private class StopwatchIOS : IStopwatch + { + private readonly Stopwatch _stopWatch; + + public StopwatchIOS() + { + _stopWatch = new Stopwatch(); + } + + public void Stop() + { + _stopWatch.Stop(); + } + + public void Reset() + { + _stopWatch.Reset(); + } + + public void Start() + { + _stopWatch.Start(); + } + + public long ElapsedMilliseconds + { + get { return _stopWatch.ElapsedMilliseconds; } + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS.Unified/VolatileServiceIOS.cs b/src/SQLite.Net.Platform.XamarinIOS.Unified/VolatileServiceIOS.cs new file mode 100644 index 000000000..efa3f33c0 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS.Unified/VolatileServiceIOS.cs @@ -0,0 +1,13 @@ +using System.Threading; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + public class VolatileServiceIOS : IVolatileService + { + public void Write(ref int transactionDepth, int depth) + { + Volatile.Write(ref transactionDepth, depth); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS/Properties/AssemblyInfo.cs b/src/SQLite.Net.Platform.XamarinIOS/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..17dc5c715 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS/Properties/AssemblyInfo.cs @@ -0,0 +1,25 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("SQLite.Net.Platform.XamarinIOS")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Øystein Krog")] +[assembly: AssemblyProduct("SQLite.Net.Platform.XamarinIOS")] +[assembly: AssemblyCopyright("Copyright ©Øystein Krog 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("d5fbb63f-29de-4148-887f-bfe12c64783b")] \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS/ReflectionServiceIOS.cs b/src/SQLite.Net.Platform.XamarinIOS/ReflectionServiceIOS.cs new file mode 100644 index 000000000..ec69f0ef1 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS/ReflectionServiceIOS.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + public class ReflectionServiceIOS : IReflectionService + { + public IEnumerable GetPublicInstanceProperties(Type mappedType) + { + return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); + } + + public object GetMemberValue(object obj, Expression expr, MemberInfo member) + { + if (member.MemberType == MemberTypes.Property) + { + var m = (PropertyInfo) member; + return m.GetValue(obj, null); + } + if (member.MemberType == MemberTypes.Field) + { + var m = (FieldInfo) member; + return m.GetValue(obj); + } + throw new NotSupportedException("MemberExpr: " + member.MemberType); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS/SQLite.Net.Platform.XamarinIOS.csproj b/src/SQLite.Net.Platform.XamarinIOS/SQLite.Net.Platform.XamarinIOS.csproj new file mode 100644 index 000000000..71a5134aa --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS/SQLite.Net.Platform.XamarinIOS.csproj @@ -0,0 +1,61 @@ + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {6377929D-6253-450D-BF4B-3E8ECE2564F7} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + SQLite.Net.Platform.XamarinIOS + Resources + SQLite.Net.Platform.XamarinIOS + + + true + full + false + bin\iPhone\Debug + DEBUG + prompt + 4 + false + true + iPhone Developer + + + none + true + bin\iPhone\Release + prompt + 4 + false + iPhone Developer + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + + + + {ABF3D656-3D1C-45D1-B6FD-41B088E5A533} + SQLite.Net + + + + + + + + + + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS/SQLiteApiIOS.cs b/src/SQLite.Net.Platform.XamarinIOS/SQLiteApiIOS.cs new file mode 100644 index 000000000..b9b189a13 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS/SQLiteApiIOS.cs @@ -0,0 +1,242 @@ +using System; +using System.Runtime.InteropServices; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + public class SQLiteApiIOS : ISQLiteApi + { + public Result Open(byte[] filename, out IDbHandle db, int flags, IntPtr zvfs) + { + IntPtr dbPtr; + Result r = SQLiteApiIOSInternal.sqlite3_open_v2(filename, out dbPtr, flags, zvfs); + db = new DbHandle(dbPtr); + return r; + } + + public ExtendedResult ExtendedErrCode(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_extended_errcode(internalDbHandle.DbPtr); + } + + public int LibVersionNumber() + { + return SQLiteApiIOSInternal.sqlite3_libversion_number(); + } + + public Result EnableLoadExtension(IDbHandle db, int onoff) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_enable_load_extension(internalDbHandle.DbPtr, onoff); + } + + public Result Close(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_close(internalDbHandle.DbPtr); + } + + public Result Initialize() + { + return SQLiteApiIOSInternal.sqlite3_initialize(); + } + public Result Shutdown() + { + return SQLiteApiIOSInternal.sqlite3_shutdown(); + } + + public Result Config(ConfigOption option) + { + return SQLiteApiIOSInternal.sqlite3_config(option); + } + + public Result BusyTimeout(IDbHandle db, int milliseconds) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_busy_timeout(internalDbHandle.DbPtr, milliseconds); + } + + public int Changes(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_changes(internalDbHandle.DbPtr); + } + + public IDbStatement Prepare2(IDbHandle db, string query) + { + var internalDbHandle = (DbHandle) db; + IntPtr stmt; + Result r = SQLiteApiIOSInternal.sqlite3_prepare_v2(internalDbHandle.DbPtr, query, query.Length, out stmt, IntPtr.Zero); + if (r != Result.OK) + { + throw SQLiteException.New(r, Errmsg16(internalDbHandle)); + } + return new DbStatement(stmt); + } + + public Result Step(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_step(internalStmt.StmtPtr); + } + + public Result Reset(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_reset(internalStmt.StmtPtr); + } + + public Result Finalize(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_finalize(internalStmt.StmtPtr); + } + + public long LastInsertRowid(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return SQLiteApiIOSInternal.sqlite3_last_insert_rowid(internalDbHandle.DbPtr); + } + + public string Errmsg16(IDbHandle db) + { + var internalDbHandle = (DbHandle) db; + return Marshal.PtrToStringUni(SQLiteApiIOSInternal.sqlite3_errmsg16(internalDbHandle.DbPtr)); + } + + public int BindParameterIndex(IDbStatement stmt, string name) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_parameter_index(internalStmt.StmtPtr, name); + } + + public int BindNull(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_null(internalStmt.StmtPtr, index); + } + + public int BindInt(IDbStatement stmt, int index, int val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_int(internalStmt.StmtPtr, index, val); + } + + public int BindInt64(IDbStatement stmt, int index, long val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_int64(internalStmt.StmtPtr, index, val); + } + + public int BindDouble(IDbStatement stmt, int index, double val) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_double(internalStmt.StmtPtr, index, val); + } + + public int BindText16(IDbStatement stmt, int index, string val, int n, IntPtr free) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_text16(internalStmt.StmtPtr, index, val, n, free); + } + + public int BindBlob(IDbStatement stmt, int index, byte[] val, int n, IntPtr free) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_bind_blob(internalStmt.StmtPtr, index, val, n, free); + } + + public int ColumnCount(IDbStatement stmt) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_count(internalStmt.StmtPtr); + } + + public string ColumnName16(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.ColumnName16(internalStmt.StmtPtr, index); + } + + public ColType ColumnType(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_type(internalStmt.StmtPtr, index); + } + + public int ColumnInt(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_int(internalStmt.StmtPtr, index); + } + + public long ColumnInt64(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_int64(internalStmt.StmtPtr, index); + } + + public double ColumnDouble(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_double(internalStmt.StmtPtr, index); + } + + public string ColumnText16(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return Marshal.PtrToStringUni(SQLiteApiIOSInternal.sqlite3_column_text16(internalStmt.StmtPtr, index)); + } + + public byte[] ColumnBlob(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.ColumnBlob(internalStmt.StmtPtr, index); + } + + public int ColumnBytes(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.sqlite3_column_bytes(internalStmt.StmtPtr, index); + } + + public byte[] ColumnByteArray(IDbStatement stmt, int index) + { + var internalStmt = (DbStatement) stmt; + return SQLiteApiIOSInternal.ColumnByteArray(internalStmt.StmtPtr, index); + } + + private struct DbHandle : IDbHandle + { + public DbHandle(IntPtr dbPtr) + : this() + { + DbPtr = dbPtr; + } + + internal IntPtr DbPtr { get; set; } + + public bool Equals(IDbHandle other) + { + return other is DbHandle && DbPtr == ((DbHandle) other).DbPtr; + } + } + + private struct DbStatement : IDbStatement + { + public DbStatement(IntPtr stmtPtr) + : this() + { + StmtPtr = stmtPtr; + } + + internal IntPtr StmtPtr { get; set; } + + public bool Equals(IDbStatement other) + { + return other is DbStatement && StmtPtr == ((DbStatement) other).StmtPtr; + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS/SQLiteApiIOSInternal.cs b/src/SQLite.Net.Platform.XamarinIOS/SQLiteApiIOSInternal.cs new file mode 100644 index 000000000..222b2798a --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS/SQLiteApiIOSInternal.cs @@ -0,0 +1,160 @@ +using System; +using System.Runtime.InteropServices; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + internal static class SQLiteApiIOSInternal + { + private const string DllName = "sqlite3"; + + [DllImport(DllName, EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern byte[] ColumnBlob(IntPtr stmt, int index); + + public static byte[] ColumnByteArray(IntPtr stmt, int index) + { + int length = sqlite3_column_bytes(stmt, index); + var result = new byte[length]; + if (length > 0) + { + Marshal.Copy(sqlite3_column_blob(stmt, index), result, 0, length); + } + return result; + } + + public static string ColumnName16(IntPtr stmt, int index) + { + return Marshal.PtrToStringUni(sqlite3_column_name16(stmt, index)); + } + + [DllImport(DllName, EntryPoint = "sqlite3_bind_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_blob(IntPtr stmt, int index, byte[] val, int n, IntPtr free); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_double", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_double(IntPtr stmt, int index, double val); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_int(IntPtr stmt, int index, int val); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_int64", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_int64(IntPtr stmt, int index, long val); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_null", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_null(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_parameter_index", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_bind_parameter_index(IntPtr stmt, [MarshalAs(UnmanagedType.LPStr)] string name); + + [DllImport(DllName, EntryPoint = "sqlite3_bind_text16", CallingConvention = CallingConvention.Cdecl, + CharSet = CharSet.Unicode)] + public static extern int sqlite3_bind_text16(IntPtr stmt, + int index, + [MarshalAs(UnmanagedType.LPWStr)] string val, + int n, + IntPtr free); + + [DllImport(DllName, EntryPoint = "sqlite3_busy_timeout", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_busy_timeout(IntPtr db, int milliseconds); + + [DllImport(DllName, EntryPoint = "sqlite3_changes", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_changes(IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_close", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_close(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_initialize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_initialize(); + + [DllImport("sqlite3", EntryPoint = "sqlite3_shutdown", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_shutdown(); + + [DllImport(DllName, EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_column_blob(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_bytes", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_bytes(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_count", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_count(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_column_double", CallingConvention = CallingConvention.Cdecl)] + public static extern double sqlite3_column_double(IntPtr stmt, int index); + + // [DllImport(DllName, EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + // private extern IntPtr ColumnNameInternal(IntPtr stmt, int index); + + // [DllImport(DllName, EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)] + // public string ColumnName(IntPtr stmt, int index) + // { + // return ColumnNameInternal(stmt, index); + // } + + [DllImport(DllName, EntryPoint = "sqlite3_column_int", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_column_int(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_int64", CallingConvention = CallingConvention.Cdecl)] + public static extern long sqlite3_column_int64(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_text16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_column_text16(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_column_type", CallingConvention = CallingConvention.Cdecl)] + public static extern ColType sqlite3_column_type(IntPtr stmt, int index); + + [DllImport(DllName, EntryPoint = "sqlite3_config", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_config(ConfigOption option); + + [DllImport(DllName, EntryPoint = "sqlite3_enable_load_extension", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_enable_load_extension(IntPtr db, int onoff); + + [DllImport(DllName, EntryPoint = "sqlite3_errmsg16", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr sqlite3_errmsg16(IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_finalize", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_finalize(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_last_insert_rowid", CallingConvention = CallingConvention.Cdecl)] + public static extern long sqlite3_last_insert_rowid(IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_open", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport(DllName, EntryPoint = "sqlite3_open16", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open16([MarshalAs(UnmanagedType.LPWStr)] string filename, out IntPtr db); + + [DllImport(DllName, EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_open_v2(byte[] filename, out IntPtr db, int flags, IntPtr zvfs); + + [DllImport(DllName, EntryPoint = "sqlite3_prepare_v2", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_prepare_v2(IntPtr db, + [MarshalAs(UnmanagedType.LPStr)] string sql, + int numBytes, + out IntPtr stmt, + IntPtr pzTail); + + [DllImport(DllName, EntryPoint = "sqlite3_reset", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_reset(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_step", CallingConvention = CallingConvention.Cdecl)] + public static extern Result sqlite3_step(IntPtr stmt); + + [DllImport(DllName, EntryPoint = "sqlite3_win32_set_directory", CallingConvention = CallingConvention.Cdecl, + CharSet = CharSet.Unicode)] + public static extern int sqlite3_win32_set_directory(uint directoryType, string directoryPath); + + [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern IntPtr LoadLibrary(string lpFileName); + + [DllImport(DllName, EntryPoint = "sqlite3_column_name16", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr sqlite3_column_name16(IntPtr stmt, int index); + + [DllImport("sqlite3", EntryPoint = "sqlite3_extended_errcode", CallingConvention = CallingConvention.Cdecl)] + public static extern ExtendedResult sqlite3_extended_errcode(IntPtr db); + + [DllImport("sqlite3", EntryPoint = "sqlite3_libversion_number", CallingConvention = CallingConvention.Cdecl)] + public static extern int sqlite3_libversion_number(); + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS/SQLitePlatformIOS.cs b/src/SQLite.Net.Platform.XamarinIOS/SQLitePlatformIOS.cs new file mode 100644 index 000000000..1a39432e7 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS/SQLitePlatformIOS.cs @@ -0,0 +1,20 @@ +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + public class SQLitePlatformIOS : ISQLitePlatform + { + public SQLitePlatformIOS() + { + SQLiteApi = new SQLiteApiIOS(); + StopwatchFactory = new StopwatchFactoryIOS(); + ReflectionService = new ReflectionServiceIOS(); + VolatileService = new VolatileServiceIOS(); + } + + public ISQLiteApi SQLiteApi { get; private set; } + public IStopwatchFactory StopwatchFactory { get; private set; } + public IReflectionService ReflectionService { get; private set; } + public IVolatileService VolatileService { get; private set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS/StopwatchFactoryIOS.cs b/src/SQLite.Net.Platform.XamarinIOS/StopwatchFactoryIOS.cs new file mode 100644 index 000000000..9d5905f20 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS/StopwatchFactoryIOS.cs @@ -0,0 +1,43 @@ +using System.Diagnostics; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + public class StopwatchFactoryIOS : IStopwatchFactory + { + public IStopwatch Create() + { + return new StopwatchIOS(); + } + + private class StopwatchIOS : IStopwatch + { + private readonly Stopwatch _stopWatch; + + public StopwatchIOS() + { + _stopWatch = new Stopwatch(); + } + + public void Stop() + { + _stopWatch.Stop(); + } + + public void Reset() + { + _stopWatch.Reset(); + } + + public void Start() + { + _stopWatch.Start(); + } + + public long ElapsedMilliseconds + { + get { return _stopWatch.ElapsedMilliseconds; } + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS/VolatileServiceIOS.cs b/src/SQLite.Net.Platform.XamarinIOS/VolatileServiceIOS.cs new file mode 100644 index 000000000..efa3f33c0 --- /dev/null +++ b/src/SQLite.Net.Platform.XamarinIOS/VolatileServiceIOS.cs @@ -0,0 +1,13 @@ +using System.Threading; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform.XamarinIOS +{ + public class VolatileServiceIOS : IVolatileService + { + public void Write(ref int transactionDepth, int depth) + { + Volatile.Write(ref transactionDepth, depth); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/AutoIncrementAttribute.cs b/src/SQLite.Net/Attributes/AutoIncrementAttribute.cs new file mode 100644 index 000000000..1834d56f0 --- /dev/null +++ b/src/SQLite.Net/Attributes/AutoIncrementAttribute.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class AutoIncrementAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/CollationAttribute.cs b/src/SQLite.Net/Attributes/CollationAttribute.cs new file mode 100644 index 000000000..5e07f87f0 --- /dev/null +++ b/src/SQLite.Net/Attributes/CollationAttribute.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class CollationAttribute : Attribute + { + public CollationAttribute(string collation) + { + Value = collation; + } + + public string Value { get; private set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/ColumnAttribute.cs b/src/SQLite.Net/Attributes/ColumnAttribute.cs new file mode 100644 index 000000000..5062891e3 --- /dev/null +++ b/src/SQLite.Net/Attributes/ColumnAttribute.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class ColumnAttribute : Attribute + { + public ColumnAttribute(string name) + { + Name = name; + } + + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/DefaultAttribute.cs b/src/SQLite.Net/Attributes/DefaultAttribute.cs new file mode 100644 index 000000000..b7d1a5b26 --- /dev/null +++ b/src/SQLite.Net/Attributes/DefaultAttribute.cs @@ -0,0 +1,22 @@ +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class DefaultAttribute : Attribute + { + public bool UseProperty { get; set; } + public object Value { get; private set; } + + /// + /// Used to set default value in database + /// + /// Will set default value to same as property. You would use proprty with backing field to set this + /// The value to set as default if usePropertyValue is false + public DefaultAttribute(bool usePropertyValue = true, object value = null) + { + Value = value; + } + + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/IgnoreAttribute.cs b/src/SQLite.Net/Attributes/IgnoreAttribute.cs new file mode 100644 index 000000000..f4539d1c4 --- /dev/null +++ b/src/SQLite.Net/Attributes/IgnoreAttribute.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class IgnoreAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/IndexedAttribute.cs b/src/SQLite.Net/Attributes/IndexedAttribute.cs new file mode 100644 index 000000000..59f73e0a5 --- /dev/null +++ b/src/SQLite.Net/Attributes/IndexedAttribute.cs @@ -0,0 +1,44 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class IndexedAttribute : Attribute + { + public IndexedAttribute() + { + } + + public IndexedAttribute(string name, int order) + { + Name = name; + Order = order; + } + + public string Name { get; set; } + public int Order { get; set; } + public virtual bool Unique { get; set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/MaxLengthAttribute.cs b/src/SQLite.Net/Attributes/MaxLengthAttribute.cs new file mode 100644 index 000000000..edcc8fd06 --- /dev/null +++ b/src/SQLite.Net/Attributes/MaxLengthAttribute.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class MaxLengthAttribute : Attribute + { + public MaxLengthAttribute(int length) + { + Value = length; + } + + public int Value { get; private set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/NotNullAttribute.cs b/src/SQLite.Net/Attributes/NotNullAttribute.cs new file mode 100644 index 000000000..a16c50ea5 --- /dev/null +++ b/src/SQLite.Net/Attributes/NotNullAttribute.cs @@ -0,0 +1,32 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class NotNullAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/PrimaryKeyAttribute.cs b/src/SQLite.Net/Attributes/PrimaryKeyAttribute.cs new file mode 100644 index 000000000..2f845241c --- /dev/null +++ b/src/SQLite.Net/Attributes/PrimaryKeyAttribute.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class PrimaryKeyAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/TableAttribute.cs b/src/SQLite.Net/Attributes/TableAttribute.cs new file mode 100644 index 000000000..a705ddb73 --- /dev/null +++ b/src/SQLite.Net/Attributes/TableAttribute.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Class)] + public class TableAttribute : Attribute + { + public TableAttribute(string name) + { + Name = name; + } + + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Attributes/UniqueAttribute.cs b/src/SQLite.Net/Attributes/UniqueAttribute.cs new file mode 100644 index 000000000..d739d236e --- /dev/null +++ b/src/SQLite.Net/Attributes/UniqueAttribute.cs @@ -0,0 +1,39 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class UniqueAttribute : IndexedAttribute + { + public override bool Unique + { + get { return true; } + set + { + /* throw? */ + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/BaseTableQuery.cs b/src/SQLite.Net/BaseTableQuery.cs new file mode 100644 index 000000000..5eae103fd --- /dev/null +++ b/src/SQLite.Net/BaseTableQuery.cs @@ -0,0 +1,32 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace SQLite.Net +{ + public abstract class BaseTableQuery + { + protected class Ordering + { + public string ColumnName { get; set; } + public bool Ascending { get; set; } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/BlobSerializerDelegate.cs b/src/SQLite.Net/BlobSerializerDelegate.cs new file mode 100644 index 000000000..06c7c7ee1 --- /dev/null +++ b/src/SQLite.Net/BlobSerializerDelegate.cs @@ -0,0 +1,44 @@ +using System; + +namespace SQLite.Net +{ + public class BlobSerializerDelegate : IBlobSerializer + { + public delegate byte[] SerializeDelegate(object obj); + public delegate bool CanSerializeDelegate(Type type); + public delegate object DeserializeDelegate(byte[] data, Type type); + + private readonly SerializeDelegate serializeDelegate; + private readonly DeserializeDelegate deserializeDelegate; + private readonly CanSerializeDelegate canDeserializeDelegate; + + public BlobSerializerDelegate (SerializeDelegate serializeDelegate, + DeserializeDelegate deserializeDelegate, + CanSerializeDelegate canDeserializeDelegate) + { + this.serializeDelegate = serializeDelegate; + this.deserializeDelegate = deserializeDelegate; + this.canDeserializeDelegate = canDeserializeDelegate; + } + + #region IBlobSerializer implementation + + public byte[] Serialize(T obj) + { + return this.serializeDelegate (obj); + } + + public object Deserialize(byte[] data, Type type) + { + return this.deserializeDelegate (data, type); + } + + public bool CanDeserialize(Type type) + { + return this.canDeserializeDelegate (type); + } + + #endregion + } +} + diff --git a/src/SQLite.Net/CreateTablesResult.cs b/src/SQLite.Net/CreateTablesResult.cs new file mode 100644 index 000000000..c4a094b81 --- /dev/null +++ b/src/SQLite.Net/CreateTablesResult.cs @@ -0,0 +1,36 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; + +namespace SQLite.Net +{ + public class CreateTablesResult + { + internal CreateTablesResult() + { + Results = new Dictionary(); + } + + public Dictionary Results { get; private set; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/DebugTraceListener.cs b/src/SQLite.Net/DebugTraceListener.cs new file mode 100644 index 000000000..e347e287e --- /dev/null +++ b/src/SQLite.Net/DebugTraceListener.cs @@ -0,0 +1,18 @@ +using System.Diagnostics; + +namespace SQLite.Net +{ + public sealed class DebugTraceListener : ITraceListener + { + public static DebugTraceListener Instance = new DebugTraceListener(); + + private DebugTraceListener() + { + } + + public void Receive(string message) + { + Debug.WriteLine(message); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/IBlobSerializer.cs b/src/SQLite.Net/IBlobSerializer.cs new file mode 100644 index 000000000..1bd623be0 --- /dev/null +++ b/src/SQLite.Net/IBlobSerializer.cs @@ -0,0 +1,41 @@ +// +// Copyright 2013, Sami M. Kallio +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +using System; +namespace SQLite.Net +{ + /// + /// The TextSerializer interface. + /// + public interface IBlobSerializer + { + /// + /// Serializes object to a byte buffer + /// + /// Object to serialize + /// Serialized blob of the object + byte[] Serialize(T obj); + + /// + /// Deserializes byte buffer into an object + /// + /// Serialized object + /// Type of object + /// Deserialized object + object Deserialize(byte[] data, Type type); + + bool CanDeserialize(Type type); + } +} \ No newline at end of file diff --git a/src/SQLite.Net/ISerializable.cs b/src/SQLite.Net/ISerializable.cs new file mode 100644 index 000000000..dbc3f1cc8 --- /dev/null +++ b/src/SQLite.Net/ISerializable.cs @@ -0,0 +1,10 @@ +using System; + +namespace SQLite.Net +{ + public interface ISerializable + { + T Serialize(); + } +} + diff --git a/src/SQLite.Net/ITraceListener.cs b/src/SQLite.Net/ITraceListener.cs new file mode 100644 index 000000000..71f6f585a --- /dev/null +++ b/src/SQLite.Net/ITraceListener.cs @@ -0,0 +1,7 @@ +namespace SQLite.Net +{ + public interface ITraceListener + { + void Receive(string message); + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/ColType.cs b/src/SQLite.Net/Interop/ColType.cs new file mode 100644 index 000000000..909ca5742 --- /dev/null +++ b/src/SQLite.Net/Interop/ColType.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +namespace SQLite.Net.Interop +{ + public enum ColType + { + Integer = 1, + Float = 2, + Text = 3, + Blob = 4, + Null = 5 + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/ConfigOption.cs b/src/SQLite.Net/Interop/ConfigOption.cs new file mode 100644 index 000000000..67a3f296a --- /dev/null +++ b/src/SQLite.Net/Interop/ConfigOption.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +namespace SQLite.Net.Interop +{ + public enum ConfigOption + { + SingleThread = 1, + MultiThread = 2, + Serialized = 3 + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/CreateFlags.cs b/src/SQLite.Net/Interop/CreateFlags.cs new file mode 100644 index 000000000..dafa23f09 --- /dev/null +++ b/src/SQLite.Net/Interop/CreateFlags.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Interop +{ + [Flags] + public enum CreateFlags + { + None = 0, + ImplicitPK = 1, // create a primary key for field called 'Id' (Orm.ImplicitPkName) + ImplicitIndex = 2, // create an index for fields ending in 'Id' (Orm.ImplicitIndexSuffix) + AllImplicit = 3, // do both above + + AutoIncPK = 4 // force PK field to be auto inc + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/ExtendedResult.cs b/src/SQLite.Net/Interop/ExtendedResult.cs new file mode 100644 index 000000000..195a4a8b9 --- /dev/null +++ b/src/SQLite.Net/Interop/ExtendedResult.cs @@ -0,0 +1,51 @@ +namespace SQLite.Net.Interop +{ + public enum ExtendedResult + { + IOErrorRead = (Result.IOError | (1 << 8)), + IOErrorShortRead = (Result.IOError | (2 << 8)), + IOErrorWrite = (Result.IOError | (3 << 8)), + IOErrorFsync = (Result.IOError | (4 << 8)), + IOErrorDirFSync = (Result.IOError | (5 << 8)), + IOErrorTruncate = (Result.IOError | (6 << 8)), + IOErrorFStat = (Result.IOError | (7 << 8)), + IOErrorUnlock = (Result.IOError | (8 << 8)), + IOErrorRdlock = (Result.IOError | (9 << 8)), + IOErrorDelete = (Result.IOError | (10 << 8)), + IOErrorBlocked = (Result.IOError | (11 << 8)), + IOErrorNoMem = (Result.IOError | (12 << 8)), + IOErrorAccess = (Result.IOError | (13 << 8)), + IOErrorCheckReservedLock = (Result.IOError | (14 << 8)), + IOErrorLock = (Result.IOError | (15 << 8)), + IOErrorClose = (Result.IOError | (16 << 8)), + IOErrorDirClose = (Result.IOError | (17 << 8)), + IOErrorSHMOpen = (Result.IOError | (18 << 8)), + IOErrorSHMSize = (Result.IOError | (19 << 8)), + IOErrorSHMLock = (Result.IOError | (20 << 8)), + IOErrorSHMMap = (Result.IOError | (21 << 8)), + IOErrorSeek = (Result.IOError | (22 << 8)), + IOErrorDeleteNoEnt = (Result.IOError | (23 << 8)), + IOErrorMMap = (Result.IOError | (24 << 8)), + LockedSharedcache = (Result.Locked | (1 << 8)), + BusyRecovery = (Result.Busy | (1 << 8)), + CannottOpenNoTempDir = (Result.CannotOpen | (1 << 8)), + CannotOpenIsDir = (Result.CannotOpen | (2 << 8)), + CannotOpenFullPath = (Result.CannotOpen | (3 << 8)), + CorruptVTab = (Result.Corrupt | (1 << 8)), + ReadonlyRecovery = (Result.ReadOnly | (1 << 8)), + ReadonlyCannotLock = (Result.ReadOnly | (2 << 8)), + ReadonlyRollback = (Result.ReadOnly | (3 << 8)), + AbortRollback = (Result.Abort | (2 << 8)), + ConstraintCheck = (Result.Constraint | (1 << 8)), + ConstraintCommitHook = (Result.Constraint | (2 << 8)), + ConstraintForeignKey = (Result.Constraint | (3 << 8)), + ConstraintFunction = (Result.Constraint | (4 << 8)), + ConstraintNotNull = (Result.Constraint | (5 << 8)), + ConstraintPrimaryKey = (Result.Constraint | (6 << 8)), + ConstraintTrigger = (Result.Constraint | (7 << 8)), + ConstraintUnique = (Result.Constraint | (8 << 8)), + ConstraintVTab = (Result.Constraint | (9 << 8)), + NoticeRecoverWAL = (Result.Notice | (1 << 8)), + NoticeRecoverRollback = (Result.Notice | (2 << 8)) + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/IDbHandle.cs b/src/SQLite.Net/Interop/IDbHandle.cs new file mode 100644 index 000000000..45abf9b1e --- /dev/null +++ b/src/SQLite.Net/Interop/IDbHandle.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +namespace SQLite.Net.Interop +{ + public interface IDbHandle + { + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/IDbStatement.cs b/src/SQLite.Net/Interop/IDbStatement.cs new file mode 100644 index 000000000..8715e900a --- /dev/null +++ b/src/SQLite.Net/Interop/IDbStatement.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +namespace SQLite.Net.Interop +{ + public interface IDbStatement + { + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/IReflectionService.cs b/src/SQLite.Net/Interop/IReflectionService.cs new file mode 100644 index 000000000..21891ee9f --- /dev/null +++ b/src/SQLite.Net/Interop/IReflectionService.cs @@ -0,0 +1,34 @@ +// +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; + +namespace SQLite.Net.Interop +{ + public interface IReflectionService + { + IEnumerable GetPublicInstanceProperties(Type mappedType); + object GetMemberValue(object obj, Expression expr, MemberInfo member); + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/ISQLiteApi.cs b/src/SQLite.Net/Interop/ISQLiteApi.cs new file mode 100644 index 000000000..b0b5f285e --- /dev/null +++ b/src/SQLite.Net/Interop/ISQLiteApi.cs @@ -0,0 +1,106 @@ +// +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; + +namespace SQLite.Net.Interop +{ + public interface ISQLiteApi + { + Result Open(byte[] filename, out IDbHandle db, int flags, IntPtr zvfs); + + // Result Open16(string filename, out IDbHandle db); + + ExtendedResult ExtendedErrCode(IDbHandle db); + + int LibVersionNumber(); + + Result EnableLoadExtension(IDbHandle db, int onoff); + + Result Close(IDbHandle db); + + Result Initialize(); + Result Shutdown(); + Result Config(ConfigOption option); + + // int SetDirectory(uint directoryType, string directoryPath); + + Result BusyTimeout(IDbHandle db, int milliseconds); + + int Changes(IDbHandle db); + + // Result Prepare2(IDbHandle db, string sql, int numBytes, out IDbStatement stmt, IntPtr pzTail); + + IDbStatement Prepare2(IDbHandle db, string query); + + Result Step(IDbStatement stmt); + + Result Reset(IDbStatement stmt); + + Result Finalize(IDbStatement stmt); + + long LastInsertRowid(IDbHandle db); + + string Errmsg16(IDbHandle db); + + // string GetErrmsg(IDbHandle db); + + int BindParameterIndex(IDbStatement stmt, string name); + + int BindNull(IDbStatement stmt, int index); + + int BindInt(IDbStatement stmt, int index, int val); + + int BindInt64(IDbStatement stmt, int index, long val); + + int BindDouble(IDbStatement stmt, int index, double val); + + int BindText16(IDbStatement stmt, int index, string val, int n, IntPtr free); + + int BindBlob(IDbStatement stmt, int index, byte[] val, int n, IntPtr free); + + int ColumnCount(IDbStatement stmt); + + // string ColumnName(IDbStatement stmt, int index); + + string ColumnName16(IDbStatement stmt, int index); + + ColType ColumnType(IDbStatement stmt, int index); + + int ColumnInt(IDbStatement stmt, int index); + + long ColumnInt64(IDbStatement stmt, int index); + + double ColumnDouble(IDbStatement stmt, int index); + + // string ColumnText(IDbStatement stmt, int index); + + string ColumnText16(IDbStatement stmt, int index); + + byte[] ColumnBlob(IDbStatement stmt, int index); + + int ColumnBytes(IDbStatement stmt, int index); + + // string ColumnText(IDbStatement stmt, int index); + + byte[] ColumnByteArray(IDbStatement stmt, int index); + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/ISQLitePlatform.cs b/src/SQLite.Net/Interop/ISQLitePlatform.cs new file mode 100644 index 000000000..181122082 --- /dev/null +++ b/src/SQLite.Net/Interop/ISQLitePlatform.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace SQLite.Net.Interop +{ + public interface ISQLitePlatform + { + ISQLiteApi SQLiteApi { get; } + IStopwatchFactory StopwatchFactory { get; } + IReflectionService ReflectionService { get; } + IVolatileService VolatileService { get; } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/IStopwatch.cs b/src/SQLite.Net/Interop/IStopwatch.cs new file mode 100644 index 000000000..a293c5b3c --- /dev/null +++ b/src/SQLite.Net/Interop/IStopwatch.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace SQLite.Net.Interop +{ + public interface IStopwatch + { + long ElapsedMilliseconds { get; } + void Stop(); + void Reset(); + void Start(); + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/IStopwatchFactory.cs b/src/SQLite.Net/Interop/IStopwatchFactory.cs new file mode 100644 index 000000000..72c800b91 --- /dev/null +++ b/src/SQLite.Net/Interop/IStopwatchFactory.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace SQLite.Net.Interop +{ + public interface IStopwatchFactory + { + IStopwatch Create(); + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/IVolatileService.cs b/src/SQLite.Net/Interop/IVolatileService.cs new file mode 100644 index 000000000..4cf4ec816 --- /dev/null +++ b/src/SQLite.Net/Interop/IVolatileService.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace SQLite.Net.Interop +{ + public interface IVolatileService + { + void Write(ref int transactionDepth, int depth); + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/Result.cs b/src/SQLite.Net/Interop/Result.cs new file mode 100644 index 000000000..7a8c46628 --- /dev/null +++ b/src/SQLite.Net/Interop/Result.cs @@ -0,0 +1,37 @@ +namespace SQLite.Net.Interop +{ + public enum Result + { + OK = 0, + Error = 1, + Internal = 2, + Perm = 3, + Abort = 4, + Busy = 5, + Locked = 6, + NoMem = 7, + ReadOnly = 8, + Interrupt = 9, + IOError = 10, + Corrupt = 11, + NotFound = 12, + Full = 13, + CannotOpen = 14, + LockErr = 15, + Empty = 16, + SchemaChngd = 17, + TooBig = 18, + Constraint = 19, + Mismatch = 20, + Misuse = 21, + NotImplementedLFS = 22, + AccessDenied = 23, + Format = 24, + Range = 25, + NonDBFile = 26, + Notice = 27, + Warning = 28, + Row = 100, + Done = 101 + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/SQLite3.cs b/src/SQLite.Net/Interop/SQLite3.cs new file mode 100644 index 000000000..0c225c408 --- /dev/null +++ b/src/SQLite.Net/Interop/SQLite3.cs @@ -0,0 +1,628 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#if WINDOWS_PHONE && !USE_WP8_NATIVE_SQLITE +#define USE_CSHARP_SQLITE +#endif + +using SQLite.Net.Interop; +#if USE_CSHARP_SQLITE +using Sqlite3 = Community.CsharpSqlite.Sqlite3; +#elif USE_WP8_NATIVE_SQLITE +using Sqlite3 = Sqlite.Sqlite3; +#else +using SQLite.Net.Interop; +#endif + +using System; +using System.Runtime.InteropServices; + +namespace SQLite.Net.Interop +{ + public static class SQLite3 + { + public enum Result : int + { + OK = 0, + Error = 1, + Internal = 2, + Perm = 3, + Abort = 4, + Busy = 5, + Locked = 6, + NoMem = 7, + ReadOnly = 8, + Interrupt = 9, + IOError = 10, + Corrupt = 11, + NotFound = 12, + Full = 13, + CannotOpen = 14, + LockErr = 15, + Empty = 16, + SchemaChngd = 17, + TooBig = 18, + Constraint = 19, + Mismatch = 20, + Misuse = 21, + NotImplementedLFS = 22, + AccessDenied = 23, + Format = 24, + Range = 25, + NonDBFile = 26, + Row = 100, + Done = 101 + } + + public enum ConfigOption : int + { + SingleThread = 1, + MultiThread = 2, + Serialized = 3 + } + +#if !USE_CSHARP_SQLITE && !USE_WP8_NATIVE_SQLITE + internal struct Sqlite3DatabaseInternal : IDbHandle + { + public IntPtr Handle { get; set; } + + public Sqlite3DatabaseInternal(IntPtr handle) : this() + { + Handle = handle; + } + } + + internal struct Sqlite3StatementInternal : IDbStatement + { + public IntPtr Handle { get; set; } + + public Sqlite3StatementInternal(IntPtr handle) + : this() + { + Handle = handle; + } + } +#elif USE_WP8_NATIVE_SQLITE + internal struct Sqlite3DatabaseInternal : IDbHandle + { + public Sqlite.Database Handle { get; set; } + + public Sqlite3DatabaseInternal(Sqlite.Database handle) + : this() + { + Handle = handle; + } + } + + internal struct Sqlite3StatementInternal : IDbStatement + { + public Sqlite.Statement Handle { get; set; } + + public Sqlite3StatementInternal(Sqlite.Statement handle) + : this() + { + Handle = handle; + } + } +#elif USE_CSHARP_SQLITE + internal struct Sqlite3DatabaseInternal : IDbHandle + { + public Sqlite3.sqlite3 Handle { get; set; } + + public Sqlite3DatabaseInternal(Sqlite3.sqlite3 handle) + : this() + { + Handle = handle; + } + } + + internal struct Sqlite3StatementInternal : IDbStatement + { + public Sqlite3.Vdbe Handle { get; set; } + + public Sqlite3StatementInternal(Sqlite3.Vdbe handle) + : this() + { + Handle = handle; + } + } +#endif + +#if !USE_CSHARP_SQLITE && !USE_WP8_NATIVE_SQLITE + public static Result Open(string filename, out IDbHandle db) + { + IntPtr dbPtr; + var r = Sqlite3Native.Open(filename, out dbPtr); + db = new Sqlite3DatabaseInternal(dbPtr); + return r; + } + + public static Result Open(string filename, out IDbHandle db, int flags, IntPtr zvfs) + { + IntPtr dbPtr; + var r = Sqlite3Native.Open(filename, out dbPtr, flags, zvfs); + db = new Sqlite3DatabaseInternal(dbPtr); + return r; + } + + public static Result Open(byte[] filename, out IDbHandle db, int flags, IntPtr zvfs) + { + IntPtr dbPtr; + var r = Sqlite3Native.Open(filename, out dbPtr, flags, zvfs); + db = new Sqlite3DatabaseInternal(dbPtr); + return r; + } + + public static Result Open16(string filename, out IDbHandle db) + { + IntPtr dbPtr; + var r = Sqlite3Native.Open(filename, out dbPtr); + db = new Sqlite3DatabaseInternal(dbPtr); + return r; + } + + public static Result EnableLoadExtension(IDbHandle db, int onoff) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return Sqlite3Native.EnableLoadExtension(internalDbHandle.Handle, onoff); + } + + public static Result Close(IDbHandle db) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return Sqlite3Native.Close(internalDbHandle.Handle); + } + + public static Result Config(ConfigOption option) + { + return Sqlite3Native.Config(option); + } + + public static int SetDirectory(uint directoryType, string directoryPath) + { + return Sqlite3Native.SetDirectory(directoryType, directoryPath); + } + + public static Result BusyTimeout(IDbHandle db, int milliseconds) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return Sqlite3Native.BusyTimeout(internalDbHandle.Handle, milliseconds); + } + + public static int Changes(IDbHandle db) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return Sqlite3Native.Changes(internalDbHandle.Handle); + } + + public static Result Prepare2(IDbHandle db, string sql, int numBytes, out IDbStatement stmt, IntPtr pzTail) + { + var internalDbHandle = (Sqlite3DatabaseInternal) db; + IntPtr stmtPtr; + var r = Sqlite3Native.Prepare2(internalDbHandle.Handle, sql, numBytes, out stmtPtr, pzTail); + stmt = new Sqlite3StatementInternal(stmtPtr); + return r; + } + + public static IDbStatement Prepare2(IDbHandle db, string query) + { + IDbStatement stmt; + var r = Prepare2 (db, query, query.Length, out stmt, IntPtr.Zero); + if (r != Result.OK) { + throw SQLiteException.New (r, GetErrmsg (db)); + } + return stmt; + } + + public static Result Step(IDbStatement stmt) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.Step(internalStmt.Handle); + } + + public static Result Reset(IDbStatement stmt) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.Reset(internalStmt.Handle); + } + + public static Result Finalize(IDbStatement stmt) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.Finalize(internalStmt.Handle); + } + + public static long LastInsertRowid(IDbHandle db) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return Sqlite3Native.LastInsertRowid(internalDbHandle.Handle); + } + + public static IntPtr Errmsg(IDbHandle db) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return Sqlite3Native.Errmsg(internalDbHandle.Handle); + } + + public static string GetErrmsg(IDbHandle db) + { + return Marshal.PtrToStringUni (Errmsg (db)); + } + + public static int BindParameterIndex(IDbStatement stmt, string name) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.BindParameterIndex(internalStmt.Handle, name); + } + + public static int BindNull(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.BindNull(internalStmt.Handle,index); + } + + public static int BindInt(IDbStatement stmt, int index, int val) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.BindInt(internalStmt.Handle, index, val); + } + + public static int BindInt64(IDbStatement stmt, int index, long val) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.BindInt64(internalStmt.Handle, index, val); + } + + public static int BindDouble(IDbStatement stmt, int index, double val) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.BindDouble(internalStmt.Handle, index, val); + } + + public static int BindText(IDbStatement stmt, int index, string val, int n, IntPtr free) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.BindText(internalStmt.Handle, index, val, n, free); + } + + public static int BindBlob(IDbStatement stmt, int index, byte[] val, int n, IntPtr free) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.BindBlob(internalStmt.Handle, index, val, n, free); + } + + public static int ColumnCount(IDbStatement stmt) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnCount(internalStmt.Handle); + } + + public static IntPtr ColumnName(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnName(internalStmt.Handle, index); + } + + static IntPtr ColumnName16Internal(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnName16Internal(internalStmt.Handle, index); + } + + public static string ColumnName16(IDbStatement stmt, int index) + { + return Marshal.PtrToStringUni(ColumnName16Internal(stmt, index)); + } + + public static ColType ColumnType(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnType(internalStmt.Handle, index); + } + + public static int ColumnInt(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnInt(internalStmt.Handle, index); + } + + public static long ColumnInt64(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnInt64(internalStmt.Handle, index); + } + + public static double ColumnDouble(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnDouble(internalStmt.Handle, index); + } + + public static IntPtr ColumnText(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnText(internalStmt.Handle, index); + } + + public static IntPtr ColumnText16(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnText16(internalStmt.Handle, index); + } + + public static IntPtr ColumnBlob(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnBlob(internalStmt.Handle, index); + } + + public static int ColumnBytes(IDbStatement stmt, int index) + { + var internalStmt = (Sqlite3StatementInternal)stmt; + return Sqlite3Native.ColumnBytes(internalStmt.Handle, index); + } + + public static string ColumnString(IDbStatement stmt, int index) + { + return Marshal.PtrToStringUni (SQLite3.ColumnText16 (stmt, index)); + } + + public static byte[] ColumnByteArray(IDbStatement stmt, int index) + { + int length = ColumnBytes (stmt, index); + var result = new byte[length]; + if (length > 0) + Marshal.Copy (ColumnBlob (stmt, index), result, 0, length); + return result; + } +#else + + public static Result Open(string filename, out IDbHandle db) + { +#if USE_WP8_NATIVE_SQLITE + Sqlite.Database internalDbHandle; + var r = (Result)Sqlite3.sqlite3_open(filename, out internalDbHandle); +#else + Sqlite3.sqlite3 internalDbHandle; + var r = (Result)Sqlite3.sqlite3_open(filename, out internalDbHandle); +#endif + db = new Sqlite3DatabaseInternal(internalDbHandle); + return r; + } + + public static Result Open(string filename, out IDbHandle db, int flags, IntPtr zVfs) + { +#if USE_WP8_NATIVE_SQLITE + Sqlite.Database internalDbHandle; + var r = (Result)Sqlite3.sqlite3_open_v2(filename, out internalDbHandle, flags, ""); +#else + Sqlite3.sqlite3 internalDbHandle; + var r = (Result)Sqlite3.sqlite3_open_v2(filename, out internalDbHandle, flags, null); +#endif + db = new Sqlite3DatabaseInternal(internalDbHandle); + return r; + } + + public static Result Close(IDbHandle db) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return (Result)Sqlite3.sqlite3_close(internalDbHandle.Handle); + } + + public static Result BusyTimeout(IDbHandle db, int milliseconds) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return (Result)Sqlite3.sqlite3_busy_timeout(internalDbHandle.Handle, milliseconds); + } + + public static int Changes(IDbHandle db) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return Sqlite3.sqlite3_changes(internalDbHandle.Handle); + } + + public static IDbStatement Prepare2(IDbHandle db, string query) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; +#if USE_WP8_NATIVE_SQLITE + Sqlite.Statement stmt; + var r = Sqlite3.sqlite3_prepare_v2(db, query, out stmt); +#else + var stmt = new Sqlite3.Vdbe(); + var r = Sqlite3.sqlite3_prepare_v2(internalDbHandle.Handle, query, -1, ref stmt, 0); +#endif + if (r != 0) + { + throw SQLiteException.New((Result)r, GetErrmsg(db)); + } + return new Sqlite3StatementInternal(stmt); + } + + public static Result Step(IDbStatement stmt) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return (Result)Sqlite3.sqlite3_step(internalStmtHandle.Handle); + } + + public static Result Reset(IDbStatement stmt) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return (Result)Sqlite3.sqlite3_reset(internalStmtHandle.Handle); + } + + public static Result Finalize(IDbStatement stmt) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return (Result)Sqlite3.sqlite3_finalize(internalStmtHandle.Handle); + } + + public static long LastInsertRowid(IDbHandle db) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return Sqlite3.sqlite3_last_insert_rowid(internalDbHandle.Handle); + } + + public static string GetErrmsg(IDbHandle db) + { + var internalDbHandle = (Sqlite3DatabaseInternal)db; + return Sqlite3.sqlite3_errmsg(internalDbHandle.Handle); + } + + public static int BindParameterIndex(IDbStatement stmt, string name) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_bind_parameter_index(internalStmtHandle.Handle, name); + } + + public static int BindNull(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_bind_null(internalStmtHandle.Handle, index); + } + + public static int BindInt(IDbStatement stmt, int index, int val) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_bind_int(internalStmtHandle.Handle, index, val); + } + + public static int BindInt64(IDbStatement stmt, int index, long val) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_bind_int64(internalStmtHandle.Handle, index, val); + } + + public static int BindDouble(IDbStatement stmt, int index, double val) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_bind_double(internalStmtHandle.Handle, index, val); + } + + public static int BindText(IDbStatement stmt, int index, string val, int n, IntPtr free) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; +#if USE_WP8_NATIVE_SQLITE + return Sqlite3.sqlite3_bind_text(internalStmtHandle.Handle, index, val, n); +#else + return Sqlite3.sqlite3_bind_text(internalStmtHandle.Handle, index, val, n, null); +#endif + } + + public static int BindBlob(IDbStatement stmt, int index, byte[] val, int n, IntPtr free) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; +#if USE_WP8_NATIVE_SQLITE + return Sqlite3.sqlite3_bind_blob(internalStmtHandle.Handle, index, val, n); +#else + return Sqlite3.sqlite3_bind_blob(internalStmtHandle.Handle, index, val, n, null); +#endif + } + + public static int ColumnCount(IDbStatement stmt) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_count(internalStmtHandle.Handle); + } + + public static string ColumnName(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_name(internalStmtHandle.Handle, index); + } + + public static string ColumnName16(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_name(internalStmtHandle.Handle, index); + } + + public static ColType ColumnType(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return (ColType)Sqlite3.sqlite3_column_type(internalStmtHandle.Handle, index); + } + + public static int ColumnInt(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_int(internalStmtHandle.Handle, index); + } + + public static long ColumnInt64(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_int64(internalStmtHandle.Handle, index); + } + + public static double ColumnDouble(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_double(internalStmtHandle.Handle, index); + } + + public static string ColumnText(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_text(internalStmtHandle.Handle, index); + } + + public static string ColumnText16(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_text(internalStmtHandle.Handle, index); + } + + public static byte[] ColumnBlob(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_blob(internalStmtHandle.Handle, index); + } + + public static int ColumnBytes(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_bytes(internalStmtHandle.Handle, index); + } + + public static string ColumnString(IDbStatement stmt, int index) + { + var internalStmtHandle = (Sqlite3StatementInternal)stmt; + return Sqlite3.sqlite3_column_text(internalStmtHandle.Handle, index); + } + + public static byte[] ColumnByteArray(IDbStatement stmt, int index) + { + return ColumnBlob(stmt, index); + } +#endif + + public enum ColType : int + { + Integer = 1, + Float = 2, + Text = 3, + Blob = 4, + Null = 5 + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Interop/SQLiteOpenFlags.cs b/src/SQLite.Net/Interop/SQLiteOpenFlags.cs new file mode 100644 index 000000000..b331feae8 --- /dev/null +++ b/src/SQLite.Net/Interop/SQLiteOpenFlags.cs @@ -0,0 +1,42 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; + +namespace SQLite.Net.Interop +{ + [Flags] + public enum SQLiteOpenFlags + { + ReadOnly = 1, + ReadWrite = 2, + Create = 4, + NoMutex = 0x8000, + FullMutex = 0x10000, + SharedCache = 0x20000, + PrivateCache = 0x40000, + ProtectionComplete = 0x00100000, + ProtectionCompleteUnlessOpen = 0x00200000, + ProtectionCompleteUntilFirstUserAuthentication = 0x00300000, + ProtectionNone = 0x00400000 + } +} \ No newline at end of file diff --git a/src/SQLite.Net/NotNullConstraintViolationException.cs b/src/SQLite.Net/NotNullConstraintViolationException.cs new file mode 100644 index 000000000..5ac9ba6df --- /dev/null +++ b/src/SQLite.Net/NotNullConstraintViolationException.cs @@ -0,0 +1,64 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections.Generic; +using System.Linq; +using SQLite.Net.Interop; + +namespace SQLite.Net +{ + public class NotNullConstraintViolationException : SQLiteException + { + protected NotNullConstraintViolationException(Result r, string message) + : this(r, message, null, null) + { + } + + protected NotNullConstraintViolationException(Result r, string message, TableMapping mapping, object obj) + : base(r, message) + { + if (mapping != null && obj != null) + { + Columns = from c in mapping.Columns + where c.IsNullable == false && c.GetValue(obj) == null + select c; + } + } + + public IEnumerable Columns { get; protected set; } + + public new static NotNullConstraintViolationException New(Result r, string message) + { + return new NotNullConstraintViolationException(r, message); + } + + public static NotNullConstraintViolationException New(Result r, string message, TableMapping mapping, object obj) + { + return new NotNullConstraintViolationException(r, message, mapping, obj); + } + + public static NotNullConstraintViolationException New(SQLiteException exception, TableMapping mapping, object obj) + { + return new NotNullConstraintViolationException(exception.Result, exception.Message, mapping, obj); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/Orm.cs b/src/SQLite.Net/Orm.cs new file mode 100755 index 000000000..dd14de08c --- /dev/null +++ b/src/SQLite.Net/Orm.cs @@ -0,0 +1,208 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using SQLite.Net.Attributes; + +namespace SQLite.Net +{ + public static class Orm + { + public const string ImplicitPkName = "Id"; + public const string ImplicitIndexSuffix = "Id"; + + public static string SqlDecl(TableMapping.Column p, bool storeDateTimeAsTicks, IBlobSerializer serializer, + IDictionary extraTypeMappings) + { + string decl = "\"" + p.Name + "\" " + SqlType(p, storeDateTimeAsTicks, serializer, extraTypeMappings) + " "; + + if (p.IsPK) + { + decl += "primary key "; + } + if (p.IsAutoInc) + { + decl += "autoincrement "; + } + if (!p.IsNullable) + { + decl += "not null "; + } + if (!string.IsNullOrEmpty(p.Collation)) + { + decl += "collate " + p.Collation + " "; + + } + if (p.DefaultValue != null) + { + decl += "default('" + p.DefaultValue + "') "; + } + + return decl; + } + + public static string SqlType(TableMapping.Column p, bool storeDateTimeAsTicks, + IBlobSerializer serializer, + IDictionary extraTypeMappings) + { + Type clrType = p.ColumnType; + var interfaces = clrType.GetTypeInfo().ImplementedInterfaces.ToList(); + + string extraMapping; + if (extraTypeMappings.TryGetValue(clrType, out extraMapping)) + { + return extraMapping; + } + + if (clrType == typeof(Boolean) || clrType == typeof(Byte) || clrType == typeof(UInt16) || + clrType == typeof(SByte) || clrType == typeof(Int16) || clrType == typeof(Int32) || + interfaces.Contains(typeof(ISerializable)) || + interfaces.Contains(typeof(ISerializable)) || + interfaces.Contains(typeof(ISerializable)) || + interfaces.Contains(typeof(ISerializable)) || + interfaces.Contains(typeof(ISerializable)) || + interfaces.Contains(typeof(ISerializable))) + { + return "integer"; + } + if (clrType == typeof(UInt32) || clrType == typeof(Int64) || + interfaces.Contains(typeof(ISerializable)) || + interfaces.Contains(typeof(ISerializable)) || + interfaces.Contains(typeof(ISerializable))) + { + return "bigint"; + } + if (clrType == typeof(Single) || clrType == typeof(Double) || clrType == typeof(Decimal) || + interfaces.Contains(typeof(ISerializable)) || + interfaces.Contains(typeof(ISerializable)) || + interfaces.Contains(typeof(ISerializable))) + { + return "float"; + } + if (clrType == typeof(String) || interfaces.Contains(typeof(ISerializable))) + { + int? len = p.MaxStringLength; + + if (len.HasValue) + return "varchar(" + len.Value + ")"; + + return "varchar"; + } + if (clrType == typeof(TimeSpan) || interfaces.Contains(typeof(ISerializable))) + { + return "bigint"; + } + if (clrType == typeof(DateTime) || interfaces.Contains(typeof(ISerializable))) + { + return storeDateTimeAsTicks ? "bigint" : "datetime"; + } + if (clrType == typeof(DateTimeOffset)) + { + return "bigint"; + } + if (clrType.GetTypeInfo().IsEnum) + { + return "integer"; + } + if (clrType == typeof(byte[]) || interfaces.Contains(typeof(ISerializable))) + { + return "blob"; + } + if (clrType == typeof(Guid) || interfaces.Contains(typeof(ISerializable))) + { + return "varchar(36)"; + } + if (serializer != null && serializer.CanDeserialize(clrType)) + { + return "blob"; + } + throw new NotSupportedException("Don't know about " + clrType); + } + + public static bool IsPK(MemberInfo p) + { + return p.GetCustomAttributes().Any(); + } + + public static string Collation(MemberInfo p) + { + foreach (var attribute in p.CustomAttributes.Where(attribute => attribute.AttributeType == typeof(CollationAttribute))) + { + return (string)attribute.ConstructorArguments[0].Value; + } + return string.Empty; + } + + public static bool IsAutoInc(MemberInfo p) + { + return p.GetCustomAttributes().Any(); + } + + public static IEnumerable GetIndices(MemberInfo p) + { + return p.GetCustomAttributes(); + } + + public static int? MaxStringLength(PropertyInfo p) + { + foreach (var attribute in p.CustomAttributes.Where(a=>a.AttributeType==typeof(MaxLengthAttribute))) + { + return (int) attribute.ConstructorArguments[0].Value; + } + return null; + } + + public static object GetDefaultValue(PropertyInfo p) + { + foreach (var attribute in p.CustomAttributes.Where(a => a.AttributeType == typeof (DefaultAttribute))) + { + try + { + var useProp = (bool) attribute.ConstructorArguments[0].Value; + + if (!useProp) + return Convert.ChangeType(attribute.ConstructorArguments[0].Value, p.PropertyType); + + var obj = Activator.CreateInstance(p.DeclaringType); + return p.GetValue(obj); + + } + catch (Exception exception) + { + throw new Exception("Unable to convert " + attribute.ConstructorArguments[0].Value + " to type " + p.PropertyType, exception); + } + } + return null; + } + + public static bool IsMarkedNotNull(MemberInfo p) + { + var attrs = p.GetCustomAttributes(true); + return attrs.Any(); + } + + } +} \ No newline at end of file diff --git a/src/SQLite.Net/PreparedSqlLiteInsertCommand.cs b/src/SQLite.Net/PreparedSqlLiteInsertCommand.cs new file mode 100644 index 000000000..dbe3bf749 --- /dev/null +++ b/src/SQLite.Net/PreparedSqlLiteInsertCommand.cs @@ -0,0 +1,129 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; +using System.Diagnostics; +using SQLite.Net.Interop; + +namespace SQLite.Net +{ + /// + /// Since the insert never changed, we only need to prepare once. + /// + public class PreparedSqlLiteInsertCommand : IDisposable + { + internal static readonly IDbStatement NullStatement = default(IDbStatement); + private readonly ISQLitePlatform _sqlitePlatform; + + internal PreparedSqlLiteInsertCommand(ISQLitePlatform platformImplementation, SQLiteConnection conn) + { + _sqlitePlatform = platformImplementation; + Connection = conn; + } + + public bool Initialized { get; set; } + + protected SQLiteConnection Connection { get; set; } + + public string CommandText { get; set; } + + protected IDbStatement Statement { get; set; } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public int ExecuteNonQuery(object[] source) + { + Connection.TraceListener.WriteLine("Executing: {0}", CommandText); + + var r = Result.OK; + + if (!Initialized) + { + Statement = Prepare(); + Initialized = true; + } + + //bind the values. + if (source != null) + { + for (int i = 0; i < source.Length; i++) + { + SQLiteCommand.BindParameter(_sqlitePlatform.SQLiteApi, Statement, i + 1, source[i], + Connection.StoreDateTimeAsTicks, Connection.Serializer); + } + } + r = _sqlitePlatform.SQLiteApi.Step(Statement); + + if (r == Result.Done) + { + int rowsAffected = _sqlitePlatform.SQLiteApi.Changes(Connection.Handle); + _sqlitePlatform.SQLiteApi.Reset(Statement); + return rowsAffected; + } + if (r == Result.Error) + { + string msg = _sqlitePlatform.SQLiteApi.Errmsg16(Connection.Handle); + _sqlitePlatform.SQLiteApi.Reset(Statement); + throw SQLiteException.New(r, msg); + } + else if (r == Result.Constraint && _sqlitePlatform.SQLiteApi.ExtendedErrCode(Connection.Handle) == ExtendedResult.ConstraintNotNull) + { + _sqlitePlatform.SQLiteApi.Reset(Statement); + throw NotNullConstraintViolationException.New(r, _sqlitePlatform.SQLiteApi.Errmsg16(Connection.Handle)); + } + _sqlitePlatform.SQLiteApi.Reset(Statement); + throw SQLiteException.New(r, r.ToString()); + } + + protected virtual IDbStatement Prepare() + { + IDbStatement stmt = _sqlitePlatform.SQLiteApi.Prepare2(Connection.Handle, CommandText); + return stmt; + } + + private void Dispose(bool disposing) + { + if (Statement != NullStatement) + { + try + { + _sqlitePlatform.SQLiteApi.Finalize(Statement); + } + finally + { + Statement = NullStatement; + Connection = null; + } + } + } + + ~PreparedSqlLiteInsertCommand() + { + Dispose(false); + } + } +} diff --git a/src/SQLite.Net/Properties/AssemblyInfo.cs b/src/SQLite.Net/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..a7156945c --- /dev/null +++ b/src/SQLite.Net/Properties/AssemblyInfo.cs @@ -0,0 +1,18 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("SQLite.Net")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Øystein Krog")] +[assembly: AssemblyProduct("SQLite.Net")] +[assembly: AssemblyCopyright("Copyright © Øystein Krog, Krueger Systems Inc.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: InternalsVisibleTo("SQLite.Net.Tests")] +[assembly: InternalsVisibleTo("SQLite.Net.Async")] \ No newline at end of file diff --git a/src/SQLite.Net/SQLite.Net.csproj b/src/SQLite.Net/SQLite.Net.csproj new file mode 100644 index 000000000..9f362fbc0 --- /dev/null +++ b/src/SQLite.Net/SQLite.Net.csproj @@ -0,0 +1,131 @@ + + + + + Debug + AnyCPU + {4971D437-0694-4297-A8CC-146CE08C3BD9} + Library + Properties + SQLite.Net + SQLite.Net + v4.5 + 512 + + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Profile259 + 10.0 + + + + + 4.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + TRACE;DEBUG + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + + + \ No newline at end of file diff --git a/src/SQLite.Net/SQLiteCommand.cs b/src/SQLite.Net/SQLiteCommand.cs new file mode 100755 index 000000000..badf9d7ad --- /dev/null +++ b/src/SQLite.Net/SQLiteCommand.cs @@ -0,0 +1,577 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using SQLite.Net.Interop; +using System.Reflection; + +namespace SQLite.Net +{ + public class SQLiteCommand + { + internal static IntPtr NegativePointer = new IntPtr(-1); + private readonly List _bindings; + private readonly SQLiteConnection _conn; + private readonly ISQLitePlatform _sqlitePlatform; + + internal SQLiteCommand(ISQLitePlatform platformImplementation, SQLiteConnection conn) + { + _sqlitePlatform = platformImplementation; + _conn = conn; + _bindings = new List(); + CommandText = ""; + } + + public string CommandText { get; set; } + + public int ExecuteNonQuery() + { + _conn.TraceListener.WriteLine("Executing: {0}", this); + + var r = Result.OK; + IDbStatement stmt = Prepare(); + r = _sqlitePlatform.SQLiteApi.Step(stmt); + Finalize(stmt); + if (r == Result.Done) + { + int rowsAffected = _sqlitePlatform.SQLiteApi.Changes(_conn.Handle); + return rowsAffected; + } + if (r == Result.Error) + { + string msg = _sqlitePlatform.SQLiteApi.Errmsg16(_conn.Handle); + throw SQLiteException.New(r, msg); + } + else if (r == Result.Constraint) + { + if (_sqlitePlatform.SQLiteApi.ExtendedErrCode(_conn.Handle) == ExtendedResult.ConstraintNotNull) + { + throw NotNullConstraintViolationException.New(r, _sqlitePlatform.SQLiteApi.Errmsg16(_conn.Handle)); + } + } + throw SQLiteException.New(r, r.ToString()); + } + + public IEnumerable ExecuteDeferredQuery() + { + return ExecuteDeferredQuery(_conn.GetMapping(typeof(T))); + } + + public List ExecuteQuery() + { + return ExecuteDeferredQuery(_conn.GetMapping(typeof(T))).ToList(); + } + + public List ExecuteQuery(TableMapping map) + { + return ExecuteDeferredQuery(map).ToList(); + } + + /// + /// Invoked every time an instance is loaded from the database. + /// + /// + /// The newly created object. + /// + /// + /// This can be overridden in combination with the + /// method to hook into the life-cycle of objects. + /// Type safety is not possible because MonoTouch does not support virtual generic methods. + /// + protected virtual void OnInstanceCreated(object obj) + { + // Can be overridden. + } + + public IEnumerable ExecuteDeferredQuery(TableMapping map) + { + _conn.TraceListener.WriteLine("Executing Query: {0}", this); + + IDbStatement stmt = Prepare(); + try + { + var cols = new TableMapping.Column[_sqlitePlatform.SQLiteApi.ColumnCount(stmt)]; + + for (int i = 0; i < cols.Length; i++) + { + string name = _sqlitePlatform.SQLiteApi.ColumnName16(stmt, i); + cols[i] = map.FindColumn(name); + } + + while (_sqlitePlatform.SQLiteApi.Step(stmt) == Result.Row) + { + object obj = Activator.CreateInstance(map.MappedType); + for (int i = 0; i < cols.Length; i++) + { + if (cols[i] == null) + { + continue; + } + ColType colType = _sqlitePlatform.SQLiteApi.ColumnType(stmt, i); + object val = ReadCol(stmt, i, colType, cols[i].ColumnType); + cols[i].SetValue(obj, val); + } + OnInstanceCreated(obj); + yield return (T)obj; + } + } + finally + { + _sqlitePlatform.SQLiteApi.Finalize(stmt); + } + } + + public T ExecuteScalar() + { + _conn.TraceListener.WriteLine("Executing Query: {0}", this); + + T val = default(T); + + IDbStatement stmt = Prepare(); + + try + { + Result r = _sqlitePlatform.SQLiteApi.Step(stmt); + if (r == Result.Row) + { + ColType colType = _sqlitePlatform.SQLiteApi.ColumnType(stmt, 0); + var clrType = Nullable.GetUnderlyingType(typeof (T)) ?? typeof (T); + val = (T)ReadCol(stmt, 0, colType, clrType); + if (colType != ColType.Null) + { + val = (T) ReadCol(stmt, 0, colType, clrType); + } + } + else if (r == Result.Done) + { + } + else + { + throw SQLiteException.New(r, _sqlitePlatform.SQLiteApi.Errmsg16(_conn.Handle)); + } + } + finally + { + Finalize(stmt); + } + + return val; + } + + public void Bind(string name, object val) + { + _bindings.Add(new Binding + { + Name = name, + Value = val + }); + } + + public void Bind(object val) + { + Bind(null, val); + } + + public override string ToString() + { + var parts = new string[1 + _bindings.Count]; + parts[0] = CommandText; + int i = 1; + foreach (Binding b in _bindings) + { + parts[i] = string.Format(" {0}: {1}", i - 1, b.Value); + i++; + } + return string.Join(Environment.NewLine, parts); + } + + private IDbStatement Prepare() + { + IDbStatement stmt = _sqlitePlatform.SQLiteApi.Prepare2(_conn.Handle, CommandText); + BindAll(stmt); + return stmt; + } + + private void Finalize(IDbStatement stmt) + { + _sqlitePlatform.SQLiteApi.Finalize(stmt); + } + + private void BindAll(IDbStatement stmt) + { + int nextIdx = 1; + foreach (Binding b in _bindings) + { + if (b.Name != null) + { + b.Index = _sqlitePlatform.SQLiteApi.BindParameterIndex(stmt, b.Name); + } + else + { + b.Index = nextIdx++; + } + + BindParameter(_sqlitePlatform.SQLiteApi, stmt, b.Index, b.Value, _conn.StoreDateTimeAsTicks, _conn.Serializer); + } + } + + internal static void BindParameter(ISQLiteApi isqLite3Api, IDbStatement stmt, int index, object value, + bool storeDateTimeAsTicks, IBlobSerializer serializer) + { + if (value == null) + { + isqLite3Api.BindNull(stmt, index); + } + else + { + if (value is Int32) + { + isqLite3Api.BindInt(stmt, index, (int)value); + } + else if (value is ISerializable) + { + isqLite3Api.BindInt(stmt, index, ((ISerializable)value).Serialize()); + } + else if (value is String) + { + isqLite3Api.BindText16(stmt, index, (string)value, -1, NegativePointer); + } + else if (value is ISerializable) + { + isqLite3Api.BindText16(stmt, index, ((ISerializable)value).Serialize(), -1, NegativePointer); + } + else if (value is Byte || value is UInt16 || value is SByte || value is Int16) + { + isqLite3Api.BindInt(stmt, index, Convert.ToInt32(value)); + } + else if (value is ISerializable) + { + isqLite3Api.BindInt(stmt, index, Convert.ToInt32(((ISerializable)value).Serialize())); + } + else if (value is ISerializable) + { + isqLite3Api.BindInt(stmt, index, Convert.ToInt32(((ISerializable)value).Serialize())); + } + else if (value is ISerializable) + { + isqLite3Api.BindInt(stmt, index, Convert.ToInt32(((ISerializable)value).Serialize())); + } + else if (value is ISerializable) + { + isqLite3Api.BindInt(stmt, index, Convert.ToInt32(((ISerializable)value).Serialize())); + } + else if (value is Boolean) + { + isqLite3Api.BindInt(stmt, index, (bool)value ? 1 : 0); + } + else if (value is ISerializable) + { + isqLite3Api.BindInt(stmt, index, ((ISerializable)value).Serialize() ? 1 : 0); + } + else if (value is UInt32 || value is Int64) + { + isqLite3Api.BindInt64(stmt, index, Convert.ToInt64(value)); + } + else if (value is ISerializable) + { + isqLite3Api.BindInt64(stmt, index, Convert.ToInt64(((ISerializable)value).Serialize())); + } + else if (value is ISerializable) + { + isqLite3Api.BindInt64(stmt, index, Convert.ToInt64(((ISerializable)value).Serialize())); + } + else if (value is Single || value is Double || value is Decimal) + { + isqLite3Api.BindDouble(stmt, index, Convert.ToDouble(value)); + } + else if (value is ISerializable) + { + isqLite3Api.BindDouble(stmt, index, Convert.ToDouble(((ISerializable)value).Serialize())); + } + else if (value is ISerializable) + { + isqLite3Api.BindDouble(stmt, index, Convert.ToDouble(((ISerializable)value).Serialize())); + } + else if (value is ISerializable) + { + isqLite3Api.BindDouble(stmt, index, Convert.ToDouble(((ISerializable)value).Serialize())); + } + else if (value is TimeSpan) + { + isqLite3Api.BindInt64(stmt, index, ((TimeSpan)value).Ticks); + } + else if (value is ISerializable) + { + isqLite3Api.BindInt64(stmt, index, ((ISerializable)value).Serialize().Ticks); + } + else if (value is DateTime) + { + if (storeDateTimeAsTicks) + { + isqLite3Api.BindInt64(stmt, index, ((DateTime)value).Ticks); + } + else + { + isqLite3Api.BindText16(stmt, index, ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss"), -1, NegativePointer); + } + } + else if (value is DateTimeOffset) + { + isqLite3Api.BindInt64(stmt, index, ((DateTimeOffset) value).UtcTicks); + } + else if (value is ISerializable) + { + if (storeDateTimeAsTicks) + { + isqLite3Api.BindInt64(stmt, index, ((ISerializable)value).Serialize().Ticks); + } + else + { + isqLite3Api.BindText16(stmt, index, ((ISerializable)value).Serialize().ToString("yyyy-MM-dd HH:mm:ss"), -1, NegativePointer); + } + } + else if (value.GetType().GetTypeInfo().IsEnum) + { + isqLite3Api.BindInt(stmt, index, Convert.ToInt32(value)); + } + else if (value is byte[]) + { + isqLite3Api.BindBlob(stmt, index, (byte[])value, ((byte[])value).Length, NegativePointer); + } + else if (value is ISerializable) + { + isqLite3Api.BindBlob(stmt, index, ((ISerializable)value).Serialize(), ((ISerializable)value).Serialize().Length, NegativePointer); + } + else if (value is Guid) + { + isqLite3Api.BindText16(stmt, index, ((Guid)value).ToString(), 72, NegativePointer); + } + else if (value is ISerializable) + { + isqLite3Api.BindText16(stmt, index, ((ISerializable)value).Serialize().ToString(), 72, NegativePointer); + } + else if (serializer != null && serializer.CanDeserialize(value.GetType())) + { + var bytes = serializer.Serialize(value); + isqLite3Api.BindBlob(stmt, index, bytes, bytes.Length, NegativePointer); + } + else + { + throw new NotSupportedException("Cannot store type: " + value.GetType()); + } + } + } + + private object ReadCol(IDbStatement stmt, int index, ColType type, Type clrType) + { + var interfaces = clrType.GetTypeInfo().ImplementedInterfaces.ToList(); + + if (type == ColType.Null) + { + return null; + } + if (clrType == typeof(String)) + { + return _sqlitePlatform.SQLiteApi.ColumnText16(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = _sqlitePlatform.SQLiteApi.ColumnText16(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(Int32)) + { + return _sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = _sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(Boolean)) + { + return _sqlitePlatform.SQLiteApi.ColumnInt(stmt, index) == 1; + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = _sqlitePlatform.SQLiteApi.ColumnInt(stmt, index) == 1; + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(double)) + { + return _sqlitePlatform.SQLiteApi.ColumnDouble(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = _sqlitePlatform.SQLiteApi.ColumnDouble(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(float)) + { + return (float)_sqlitePlatform.SQLiteApi.ColumnDouble(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = (float)_sqlitePlatform.SQLiteApi.ColumnDouble(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(TimeSpan)) + { + return new TimeSpan(_sqlitePlatform.SQLiteApi.ColumnInt64(stmt, index)); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = new TimeSpan(_sqlitePlatform.SQLiteApi.ColumnInt64(stmt, index)); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(DateTime)) + { + if (_conn.StoreDateTimeAsTicks) + { + return new DateTime(_sqlitePlatform.SQLiteApi.ColumnInt64(stmt, index)); + } + return DateTime.Parse(_sqlitePlatform.SQLiteApi.ColumnText16(stmt, index)); + } + if (clrType == typeof (DateTimeOffset)) + { + return new DateTimeOffset(_sqlitePlatform.SQLiteApi.ColumnInt64(stmt, index), TimeSpan.Zero); + } + if (interfaces.Contains(typeof(ISerializable))) + { + DateTime value; + if (_conn.StoreDateTimeAsTicks) + { + value = new DateTime(_sqlitePlatform.SQLiteApi.ColumnInt64(stmt, index)); + } + else + { + value = DateTime.Parse(_sqlitePlatform.SQLiteApi.ColumnText16(stmt, index)); + } + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType.GetTypeInfo().IsEnum) + { + return _sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + } + if (clrType == typeof(Int64)) + { + return _sqlitePlatform.SQLiteApi.ColumnInt64(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = _sqlitePlatform.SQLiteApi.ColumnInt64(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(UInt32)) + { + return (uint)_sqlitePlatform.SQLiteApi.ColumnInt64(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = (uint)_sqlitePlatform.SQLiteApi.ColumnInt64(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(decimal)) + { + return (decimal)_sqlitePlatform.SQLiteApi.ColumnDouble(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = (decimal)_sqlitePlatform.SQLiteApi.ColumnDouble(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(Byte)) + { + return (byte)_sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = (byte)_sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(UInt16)) + { + return (ushort)_sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = (ushort)_sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(Int16)) + { + return (short)_sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = (short)_sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(sbyte)) + { + return (sbyte)_sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = (sbyte)_sqlitePlatform.SQLiteApi.ColumnInt(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(byte[])) + { + return _sqlitePlatform.SQLiteApi.ColumnByteArray(stmt, index); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = _sqlitePlatform.SQLiteApi.ColumnByteArray(stmt, index); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (clrType == typeof(Guid)) + { + return new Guid(_sqlitePlatform.SQLiteApi.ColumnText16(stmt, index)); + } + if (interfaces.Contains(typeof(ISerializable))) + { + var value = new Guid(_sqlitePlatform.SQLiteApi.ColumnText16(stmt, index)); + return Activator.CreateInstance(clrType, new object[]{ value }); + } + if (_conn.Serializer != null && _conn.Serializer.CanDeserialize(clrType)) + { + var bytes = _sqlitePlatform.SQLiteApi.ColumnByteArray(stmt, index); + return _conn.Serializer.Deserialize(bytes, clrType); + } + throw new NotSupportedException("Don't know how to read " + clrType); + } + + private class Binding + { + public string Name { get; set; } + + public object Value { get; set; } + + public int Index { get; set; } + } + } +} diff --git a/src/SQLite.Net/SQLiteConnection.cs b/src/SQLite.Net/SQLiteConnection.cs new file mode 100644 index 000000000..442162ae8 --- /dev/null +++ b/src/SQLite.Net/SQLiteConnection.cs @@ -0,0 +1,1571 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; + +namespace SQLite.Net +{ + /// + /// Represents an open connection to a SQLite database. + /// + public class SQLiteConnection : IDisposable + { + internal static readonly IDbHandle NullHandle = default(IDbHandle); + + /// + /// Used to list some code that we want the MonoTouch linker + /// to see, but that we never want to actually execute. + /// + #pragma warning disable 649 + private static bool _preserveDuringLinkMagic; + #pragma warning restore 649 + + private readonly Random _rand = new Random(); + + private TimeSpan _busyTimeout; + private long _elapsedMilliseconds; + private Dictionary _mappings; + private bool _open; + private IStopwatch _sw; + private Dictionary _tables; + + private int _transactionDepth; + + static SQLiteConnection() + { + if (_preserveDuringLinkMagic) + { + var ti = new ColumnInfo(); + ti.Name = "magic"; + } + } + + /// + /// Constructs a new SQLiteConnection and opens a SQLite database specified by databasePath. + /// + /// + /// + /// Specifies the path to the database file. + /// + /// + /// Specifies whether to store DateTime properties as ticks (true) or strings (false). You + /// absolutely do want to store them as Ticks in all new projects. The default of false is + /// only here for backwards compatibility. There is a *significant* speed advantage, with no + /// down sides, when setting storeDateTimeAsTicks = true. + /// + /// + /// Blob serializer to use for storing undefined and complex data structures. If left null + /// these types will thrown an exception as usual. + /// + /// + /// Any extra type mappings that you wish to use for overriding the default for creating + /// column definitions for SQLite DDL in the class Orm (snake in Swedish). + /// + public SQLiteConnection(ISQLitePlatform sqlitePlatform, string databasePath, bool storeDateTimeAsTicks = false, IBlobSerializer serializer = null, IDictionary extraTypeMappings = null) + : this( + sqlitePlatform, databasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create, storeDateTimeAsTicks, serializer, extraTypeMappings) + { + } + + + /// + /// Constructs a new SQLiteConnection and opens a SQLite database specified by databasePath. + /// + /// + /// + /// Specifies the path to the database file. + /// + /// + /// + /// Specifies whether to store DateTime properties as ticks (true) or strings (false). You + /// absolutely do want to store them as Ticks in all new projects. The default of false is + /// only here for backwards compatibility. There is a *significant* speed advantage, with no + /// down sides, when setting storeDateTimeAsTicks = true. + /// + /// + /// Blob serializer to use for storing undefined and complex data structures. If left null + /// these types will thrown an exception as usual. + /// + /// + /// Any extra type mappings that you wish to use for overriding the default for creating + /// column definitions for SQLite DDL in the class Orm (snake in Swedish). + /// + public SQLiteConnection(ISQLitePlatform sqlitePlatform, string databasePath, SQLiteOpenFlags openFlags, + bool storeDateTimeAsTicks = false, IBlobSerializer serializer = null, + IDictionary extraTypeMappings = null) + { + ExtraTypeMappings = extraTypeMappings ?? new Dictionary(); + Serializer = serializer; + Platform = sqlitePlatform; + + if (string.IsNullOrEmpty(databasePath)) + { + throw new ArgumentException("Must be specified", "databasePath"); + } + + DatabasePath = databasePath; + + IDbHandle handle; + byte[] databasePathAsBytes = GetNullTerminatedUtf8(DatabasePath); + Result r = Platform.SQLiteApi.Open(databasePathAsBytes, out handle, (int)openFlags, IntPtr.Zero); + + Handle = handle; + if (r != Result.OK) + { + throw SQLiteException.New(r, String.Format("Could not open database file: {0} ({1})", DatabasePath, r)); + } + _open = true; + + StoreDateTimeAsTicks = storeDateTimeAsTicks; + + BusyTimeout = TimeSpan.FromSeconds(0.1); + } + + public IBlobSerializer Serializer { get; private set; } + + public IDbHandle Handle { get; private set; } + + public string DatabasePath { get; private set; } + + public bool TimeExecution { get; set; } + + public ITraceListener TraceListener { get; set; } + + public bool StoreDateTimeAsTicks { get; private set; } + + public IDictionary ExtraTypeMappings { get; private set; } + + /// + /// Sets a busy handler to sleep the specified amount of time when a table is locked. + /// The handler will sleep multiple times until a total time of has accumulated. + /// + public TimeSpan BusyTimeout + { + get { return _busyTimeout; } + set + { + _busyTimeout = value; + if (Handle != NullHandle) + { + Platform.SQLiteApi.BusyTimeout(Handle, (int)_busyTimeout.TotalMilliseconds); + } + } + } + + /// + /// Returns the mappings from types to tables that the connection + /// currently understands. + /// + public IEnumerable TableMappings + { + get { return _tables != null ? _tables.Values : Enumerable.Empty(); } + } + + /// + /// Whether has been called and the database is waiting for a . + /// + public bool IsInTransaction + { + get { return _transactionDepth > 0; } + } + + public ISQLitePlatform Platform { get; private set; } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public void EnableLoadExtension(int onoff) + { + Result r = Platform.SQLiteApi.EnableLoadExtension(Handle, onoff); + if (r != Result.OK) + { + string msg = Platform.SQLiteApi.Errmsg16(Handle); + throw SQLiteException.New(r, msg); + } + } + + private static byte[] GetNullTerminatedUtf8(string s) + { + int utf8Length = Encoding.UTF8.GetByteCount(s); + var bytes = new byte[utf8Length + 1]; + utf8Length = Encoding.UTF8.GetBytes(s, 0, s.Length, bytes, 0); + return bytes; + } + + /// + /// Retrieves the mapping that is automatically generated for the given type. + /// + /// + /// The type whose mapping to the database is returned. + /// + /// + /// Optional flags allowing implicit PK and indexes based on naming conventions + /// + /// + /// The mapping represents the schema of the columns of the database and contains + /// methods to set and get properties of objects. + /// + public TableMapping GetMapping(Type type, CreateFlags createFlags = CreateFlags.None) + { + if (_mappings == null) + { + _mappings = new Dictionary(); + } + TableMapping map; + if (!_mappings.TryGetValue(type.FullName, out map)) + { + map = new TableMapping(Platform, type, createFlags); + _mappings[type.FullName] = map; + } + return map; + } + + /// + /// Retrieves the mapping that is automatically generated for the given type. + /// + /// + /// The mapping represents the schema of the columns of the database and contains + /// methods to set and get properties of objects. + /// + public TableMapping GetMapping() + { + return GetMapping(typeof(T)); + } + + /// + /// Executes a "drop table" on the database. This is non-recoverable. + /// + public int DropTable() + { + TableMapping map = GetMapping(typeof(T)); + + string query = string.Format("drop table if exists \"{0}\"", map.TableName); + + return Execute(query); + } + + /// + /// Executes a "create table if not exists" on the database. It also + /// creates any specified indexes on the columns of the table. It uses + /// a schema automatically generated from the specified type. You can + /// later access this schema by calling GetMapping. + /// + /// + /// The number of entries added to the database schema. + /// + public int CreateTable(CreateFlags createFlags = CreateFlags.None) + { + return CreateTable(typeof(T), createFlags); + } + + /// + /// Executes a "create table if not exists" on the database. It also + /// creates any specified indexes on the columns of the table. It uses + /// a schema automatically generated from the specified type. You can + /// later access this schema by calling GetMapping. + /// + /// Type to reflect to a database table. + /// Optional flags allowing implicit PK and indexes based on naming conventions. + /// + /// The number of entries added to the database schema. + /// + public int CreateTable(Type ty, CreateFlags createFlags = CreateFlags.None) + { + if (_tables == null) + { + _tables = new Dictionary(); + } + TableMapping map; + if (!_tables.TryGetValue(ty.FullName, out map)) + { + map = GetMapping(ty, createFlags); + _tables.Add(ty.FullName, map); + } + string query = "create table if not exists \"" + map.TableName + "\"(\n"; + + IEnumerable decls = map.Columns.Select(p => Orm.SqlDecl(p, StoreDateTimeAsTicks, this.Serializer, this.ExtraTypeMappings)); + string decl = string.Join(",\n", decls.ToArray()); + query += decl; + query += ")"; + + int count = Execute(query); + + if (count == 0) + { + //Possible bug: This always seems to return 0? + // Table already exists, migrate it + MigrateTable(map); + } + + var indexes = new Dictionary(); + foreach (TableMapping.Column c in map.Columns) + { + foreach (IndexedAttribute i in c.Indices) + { + string iname = i.Name ?? map.TableName + "_" + c.Name; + IndexInfo iinfo; + if (!indexes.TryGetValue(iname, out iinfo)) + { + iinfo = new IndexInfo + { + IndexName = iname, + TableName = map.TableName, + Unique = i.Unique, + Columns = new List() + }; + indexes.Add(iname, iinfo); + } + + if (i.Unique != iinfo.Unique) + { + throw new Exception( + "All the columns in an index must have the same value for their Unique property"); + } + + iinfo.Columns.Add(new IndexedColumn + { + Order = i.Order, + ColumnName = c.Name + }); + } + } + + foreach (var indexName in indexes.Keys) + { + var index = indexes[indexName]; + var columns = index.Columns.OrderBy(i => i.Order).Select(i => i.ColumnName).ToArray(); + count += CreateIndex(indexName, index.TableName, columns, index.Unique); + } + + return count; + } + + /// + /// Creates an index for the specified table and columns. + /// + /// Name of the index to create + /// Name of the database table + /// An array of column names to index + /// Whether the index should be unique + public int CreateIndex(string indexName, string tableName, string[] columnNames, bool unique = false) + { + const string sqlFormat = "create {2} index if not exists \"{3}\" on \"{0}\"(\"{1}\")"; + var sql = String.Format(sqlFormat, tableName, string.Join("\", \"", columnNames), unique ? "unique" : "", indexName); + return Execute(sql); + } + + /// + /// Creates an index for the specified table and column. + /// + /// Name of the index to create + /// Name of the database table + /// Name of the column to index + /// Whether the index should be unique + public int CreateIndex(string indexName, string tableName, string columnName, bool unique = false) + { + return CreateIndex(indexName, tableName, new string[] { columnName }, unique); + } + + /// + /// Creates an index for the specified table and column. + /// + /// Name of the database table + /// Name of the column to index + /// Whether the index should be unique + public int CreateIndex(string tableName, string columnName, bool unique = false) + { + return CreateIndex(tableName + "_" + columnName, tableName, columnName, unique); + } + + /// + /// Creates an index for the specified table and columns. + /// + /// Name of the database table + /// An array of column names to index + /// Whether the index should be unique + public int CreateIndex(string tableName, string[] columnNames, bool unique = false) + { + return CreateIndex(tableName + "_" + string.Join("_", columnNames), tableName, columnNames, unique); + } + + /// + /// Creates an index for the specified object property. + /// e.g. CreateIndex{Client}(c => c.Name); + /// + /// Type to reflect to a database table. + /// Property to index + /// Whether the index should be unique + public void CreateIndex(Expression> property, bool unique = false) + { + MemberExpression mx; + if (property.Body.NodeType == ExpressionType.Convert) + { + mx = ((UnaryExpression)property.Body).Operand as MemberExpression; + } + else + { + mx = (property.Body as MemberExpression); + } + var propertyInfo = mx.Member as PropertyInfo; + if (propertyInfo == null) + { + throw new ArgumentException("The lambda expression 'property' should point to a valid Property"); + } + + string propName = propertyInfo.Name; + + TableMapping map = GetMapping(); + string colName = map.FindColumnWithPropertyName(propName).Name; + + CreateIndex(map.TableName, colName, unique); + } + + public List GetTableInfo(string tableName) + { + string query = "pragma table_info(\"" + tableName + "\")"; + return Query(query); + } + + private void MigrateTable(TableMapping map) + { + List existingCols = GetTableInfo(map.TableName); + + var toBeAdded = new List(); + + foreach (TableMapping.Column p in map.Columns) + { + bool found = false; + foreach (ColumnInfo c in existingCols) + { + found = (string.Compare(p.Name, c.Name, StringComparison.OrdinalIgnoreCase) == 0); + if (found) + { + break; + } + } + if (!found) + { + toBeAdded.Add(p); + } + } + + foreach (TableMapping.Column p in toBeAdded) + { + string addCol = "alter table \"" + map.TableName + "\" add column " + + Orm.SqlDecl(p, StoreDateTimeAsTicks, this.Serializer, this.ExtraTypeMappings); + Execute(addCol); + } + } + + /// + /// Creates a new SQLiteCommand. Can be overridden to provide a sub-class. + /// + /// + protected virtual SQLiteCommand NewCommand() + { + return new SQLiteCommand(Platform, this); + } + + /// + /// Creates a new SQLiteCommand given the command text with arguments. Place a '?' + /// in the command text for each of the arguments. + /// + /// + /// The fully escaped SQL. + /// + /// + /// Arguments to substitute for the occurences of '?' in the command text. + /// + /// + /// A + /// + public SQLiteCommand CreateCommand(string cmdText, params object[] args) + { + if (!_open) + { + throw SQLiteException.New(Result.Error, "Cannot create commands from unopened database"); + } + + SQLiteCommand cmd = NewCommand(); + cmd.CommandText = cmdText; + foreach (object o in args) + { + cmd.Bind(o); + } + return cmd; + } + + /// + /// Creates a SQLiteCommand given the command text (SQL) with arguments. Place a '?' + /// in the command text for each of the arguments and then executes that command. + /// Use this method instead of Query when you don't expect rows back. Such cases include + /// INSERTs, UPDATEs, and DELETEs. + /// You can set the Trace or TimeExecution properties of the connection + /// to profile execution. + /// + /// + /// The fully escaped SQL. + /// + /// + /// Arguments to substitute for the occurences of '?' in the query. + /// + /// + /// The number of rows modified in the database as a result of this execution. + /// + public int Execute(string query, params object[] args) + { + SQLiteCommand cmd = CreateCommand(query, args); + + if (TimeExecution) + { + if (_sw == null) + { + _sw = Platform.StopwatchFactory.Create(); + } + _sw.Reset(); + _sw.Start(); + } + + int r = cmd.ExecuteNonQuery(); + + if (TimeExecution) + { + _sw.Stop(); + _elapsedMilliseconds += _sw.ElapsedMilliseconds; + + this.TraceListener.WriteLine("Finished in {0} ms ({1:0.0} s total)", _sw.ElapsedMilliseconds, _elapsedMilliseconds / 1000.0); + } + + return r; + } + + public T ExecuteScalar(string query, params object[] args) + { + SQLiteCommand cmd = CreateCommand(query, args); + + if (TimeExecution) + { + if (_sw == null) + { + _sw = Platform.StopwatchFactory.Create(); + } + _sw.Reset(); + _sw.Start(); + } + + var r = cmd.ExecuteScalar(); + + if (TimeExecution) + { + _sw.Stop(); + _elapsedMilliseconds += _sw.ElapsedMilliseconds; + + this.TraceListener.WriteLine("Finished in {0} ms ({1:0.0} s total)", _sw.ElapsedMilliseconds, _elapsedMilliseconds / 1000.0); + } + + return r; + } + + /// + /// Creates a SQLiteCommand given the command text (SQL) with arguments. Place a '?' + /// in the command text for each of the arguments and then executes that command. + /// It returns each row of the result using the mapping automatically generated for + /// the given type. + /// + /// + /// The fully escaped SQL. + /// + /// + /// Arguments to substitute for the occurences of '?' in the query. + /// + /// + /// An enumerable with one result for each row returned by the query. + /// + public List Query(string query, params object[] args) where T : new() + { + SQLiteCommand cmd = CreateCommand(query, args); + return cmd.ExecuteQuery(); + } + + /// + /// Creates a SQLiteCommand given the command text (SQL) with arguments. Place a '?' + /// in the command text for each of the arguments and then executes that command. + /// It returns each row of the result using the mapping automatically generated for + /// the given type. + /// + /// + /// The fully escaped SQL. + /// + /// + /// Arguments to substitute for the occurences of '?' in the query. + /// + /// + /// An enumerable with one result for each row returned by the query. + /// The enumerator will call sqlite3_step on each call to MoveNext, so the database + /// connection must remain open for the lifetime of the enumerator. + /// + public IEnumerable DeferredQuery(string query, params object[] args) where T : new() + { + SQLiteCommand cmd = CreateCommand(query, args); + return cmd.ExecuteDeferredQuery(); + } + + /// + /// Creates a SQLiteCommand given the command text (SQL) with arguments. Place a '?' + /// in the command text for each of the arguments and then executes that command. + /// It returns each row of the result using the specified mapping. This function is + /// only used by libraries in order to query the database via introspection. It is + /// normally not used. + /// + /// + /// A to use to convert the resulting rows + /// into objects. + /// + /// + /// The fully escaped SQL. + /// + /// + /// Arguments to substitute for the occurences of '?' in the query. + /// + /// + /// An enumerable with one result for each row returned by the query. + /// + public List Query(TableMapping map, string query, params object[] args) + { + SQLiteCommand cmd = CreateCommand(query, args); + return cmd.ExecuteQuery(map); + } + + /// + /// Creates a SQLiteCommand given the command text (SQL) with arguments. Place a '?' + /// in the command text for each of the arguments and then executes that command. + /// It returns each row of the result using the specified mapping. This function is + /// only used by libraries in order to query the database via introspection. It is + /// normally not used. + /// + /// + /// A to use to convert the resulting rows + /// into objects. + /// + /// + /// The fully escaped SQL. + /// + /// + /// Arguments to substitute for the occurences of '?' in the query. + /// + /// + /// An enumerable with one result for each row returned by the query. + /// The enumerator will call sqlite3_step on each call to MoveNext, so the database + /// connection must remain open for the lifetime of the enumerator. + /// + public IEnumerable DeferredQuery(TableMapping map, string query, params object[] args) + { + SQLiteCommand cmd = CreateCommand(query, args); + return cmd.ExecuteDeferredQuery(map); + } + + /// + /// Returns a queryable interface to the table represented by the given type. + /// + /// + /// A queryable object that is able to translate Where, OrderBy, and Take + /// queries into native SQL. + /// + public TableQuery Table() where T : new() + { + return new TableQuery(Platform, this); + } + + /// + /// Attempts to retrieve an object with the given primary key from the table + /// associated with the specified type. Use of this method requires that + /// the given type have a designated PrimaryKey (using the PrimaryKeyAttribute). + /// + /// + /// The primary key. + /// + /// + /// The object with the given primary key. Throws a not found exception + /// if the object is not found. + /// + public T Get(object pk) where T : new() + { + TableMapping map = GetMapping(typeof(T)); + return Query(map.GetByPrimaryKeySql, pk).First(); + } + + /// + /// Attempts to retrieve the first object that matches the predicate from the table + /// associated with the specified type. + /// + /// + /// A predicate for which object to find. + /// + /// + /// The object that matches the given predicate. Throws a not found exception + /// if the object is not found. + /// + public T Get(Expression> predicate) where T : new() + { + return Table().Where(predicate).First(); + } + + /// + /// Attempts to retrieve an object with the given primary key from the table + /// associated with the specified type. Use of this method requires that + /// the given type have a designated PrimaryKey (using the PrimaryKeyAttribute). + /// + /// + /// The primary key. + /// + /// + /// The object with the given primary key or null + /// if the object is not found. + /// + public T Find(object pk) where T : new() + { + TableMapping map = GetMapping(typeof(T)); + return Query(map.GetByPrimaryKeySql, pk).FirstOrDefault(); + } + + /// + /// Attempts to retrieve an object with the given primary key from the table + /// associated with the specified type. Use of this method requires that + /// the given type have a designated PrimaryKey (using the PrimaryKeyAttribute). + /// + /// + /// The primary key. + /// + /// + /// The TableMapping used to identify the object type. + /// + /// + /// The object with the given primary key or null + /// if the object is not found. + /// + public object Find(object pk, TableMapping map) + { + return Query(map, map.GetByPrimaryKeySql, pk).FirstOrDefault(); + } + + /// + /// Attempts to retrieve the first object that matches the predicate from the table + /// associated with the specified type. + /// + /// + /// A predicate for which object to find. + /// + /// + /// The object that matches the given predicate or null + /// if the object is not found. + /// + public T Find(Expression> predicate) where T : new() + { + return Table().Where(predicate).FirstOrDefault(); + } + + /// + /// Begins a new transaction. Call to end the transaction. + /// + /// Throws if a transaction has already begun. + public void BeginTransaction() + { + // The BEGIN command only works if the transaction stack is empty, + // or in other words if there are no pending transactions. + // If the transaction stack is not empty when the BEGIN command is invoked, + // then the command fails with an error. + // Rather than crash with an error, we will just ignore calls to BeginTransaction + // that would result in an error. + if (Interlocked.CompareExchange(ref _transactionDepth, 1, 0) == 0) + { + try + { + Execute("begin transaction"); + } + catch (Exception ex) + { + var sqlExp = ex as SQLiteException; + if (sqlExp != null) + { + // It is recommended that applications respond to the errors listed below + // by explicitly issuing a ROLLBACK command. + // TODO: This rollback failsafe should be localized to all throw sites. + switch (sqlExp.Result) + { + case Result.IOError: + case Result.Full: + case Result.Busy: + case Result.NoMem: + case Result.Interrupt: + RollbackTo(null, true); + break; + } + } + else + { + // Call decrement and not VolatileWrite in case we've already + // created a transaction point in SaveTransactionPoint since the catch. + Interlocked.Decrement(ref _transactionDepth); + } + + throw; + } + } + else + { + // Calling BeginTransaction on an already open transaction is invalid + throw new InvalidOperationException("Cannot begin a transaction while already in a transaction."); + } + } + + /// + /// Creates a savepoint in the database at the current point in the transaction timeline. + /// Begins a new transaction if one is not in progress. + /// Call to undo transactions since the returned savepoint. + /// Call to commit transactions after the savepoint returned here. + /// Call to end the transaction, committing all changes. + /// + /// A string naming the savepoint. + public string SaveTransactionPoint() + { + int depth = Interlocked.Increment(ref _transactionDepth) - 1; + string retVal = "S" + _rand.Next(short.MaxValue) + "D" + depth; + + try + { + Execute("savepoint " + retVal); + } + catch (Exception ex) + { + var sqlExp = ex as SQLiteException; + if (sqlExp != null) + { + // It is recommended that applications respond to the errors listed below + // by explicitly issuing a ROLLBACK command. + // TODO: This rollback failsafe should be localized to all throw sites. + switch (sqlExp.Result) + { + case Result.IOError: + case Result.Full: + case Result.Busy: + case Result.NoMem: + case Result.Interrupt: + RollbackTo(null, true); + break; + } + } + else + { + Interlocked.Decrement(ref _transactionDepth); + } + + throw; + } + + return retVal; + } + + /// + /// Rolls back the transaction that was begun by or + /// . + /// + public void Rollback() + { + RollbackTo(null, false); + } + + /// + /// Rolls back the savepoint created by or SaveTransactionPoint. + /// + /// + /// The name of the savepoint to roll back to, as returned by . + /// If savepoint is null or empty, this method is equivalent to a call to + /// + public void RollbackTo(string savepoint) + { + RollbackTo(savepoint, false); + } + + /// + /// Rolls back the transaction that was begun by . + /// + /// the savepoint name/key + /// true to avoid throwing exceptions, false otherwise + private void RollbackTo(string savepoint, bool noThrow) + { + // Rolling back without a TO clause rolls backs all transactions + // and leaves the transaction stack empty. + try + { + if (String.IsNullOrEmpty(savepoint)) + { + if (Interlocked.Exchange(ref _transactionDepth, 0) > 0) + { + Execute("rollback"); + } + } + else + { + DoSavePointExecute(savepoint, "rollback to "); + } + } + catch (SQLiteException) + { + if (!noThrow) + { + throw; + } + } + // No need to rollback if there are no transactions open. + } + + /// + /// Releases a savepoint returned from . Releasing a savepoint + /// makes changes since that savepoint permanent if the savepoint began the transaction, + /// or otherwise the changes are permanent pending a call to . + /// The RELEASE command is like a COMMIT for a SAVEPOINT. + /// + /// + /// The name of the savepoint to release. The string should be the result of a call to + /// + /// + public void Release(string savepoint) + { + DoSavePointExecute(savepoint, "release "); + } + + private void DoSavePointExecute(string savepoint, string cmd) + { + // Validate the savepoint + int firstLen = savepoint.IndexOf('D'); + if (firstLen >= 2 && savepoint.Length > firstLen + 1) + { + int depth; + if (Int32.TryParse(savepoint.Substring(firstLen + 1), out depth)) + { + // TODO: Mild race here, but inescapable without locking almost everywhere. + if (0 <= depth && depth < _transactionDepth) + { + Platform.VolatileService.Write(ref _transactionDepth, depth); + Execute(cmd + savepoint); + return; + } + } + } + + throw new ArgumentException( + "savePoint is not valid, and should be the result of a call to SaveTransactionPoint.", "savePoint"); + } + + /// + /// Commits the transaction that was begun by . + /// + public void Commit() + { + if (Interlocked.Exchange(ref _transactionDepth, 0) != 0) + { + Execute("commit"); + } + // Do nothing on a commit with no open transaction + } + + /// + /// Executes + /// + /// within a (possibly nested) transaction by wrapping it in a SAVEPOINT. If an + /// exception occurs the whole transaction is rolled back, not just the current savepoint. The exception + /// is rethrown. + /// + /// + /// The to perform within a transaction. + /// + /// can contain any number + /// of operations on the connection but should never call or + /// . + /// + public void RunInTransaction(Action action) + { + try + { + string savePoint = SaveTransactionPoint(); + action(); + Release(savePoint); + } + catch (Exception) + { + Rollback(); + throw; + } + } + + /// + /// Inserts all specified objects. + /// + /// + /// An of the objects to insert. + /// + /// + /// The number of rows added to the table. + /// + public int InsertAll(IEnumerable objects) + { + int c = 0; + RunInTransaction(() => + { + foreach (object r in objects) + { + c += Insert(r); + } + }); + return c; + } + + /// + /// Inserts all specified objects. + /// + /// + /// An of the objects to insert. + /// + /// + /// Literal SQL code that gets placed into the command. INSERT {extra} INTO ... + /// + /// + /// The number of rows added to the table. + /// + public int InsertAll(IEnumerable objects, string extra) + { + int c = 0; + RunInTransaction(() => + { + foreach (object r in objects) + { + c += Insert(r, extra); + } + }); + return c; + } + + /// + /// Inserts all specified objects. + /// + /// + /// An of the objects to insert. + /// + /// + /// The type of object to insert. + /// + /// + /// The number of rows added to the table. + /// + public int InsertAll(IEnumerable objects, Type objType) + { + int c = 0; + RunInTransaction(() => + { + foreach (object r in objects) + { + c += Insert(r, objType); + } + }); + return c; + } + + /// + /// Inserts the given object and retrieves its + /// auto incremented primary key if it has one. + /// + /// + /// The object to insert. + /// + /// + /// The number of rows added to the table. + /// + public int Insert(object obj) + { + if (obj == null) + { + return 0; + } + return Insert(obj, "", obj.GetType()); + } + + /// + /// Inserts the given object and retrieves its + /// auto incremented primary key if it has one. + /// If a UNIQUE constraint violation occurs with + /// some pre-existing object, this function deletes + /// the old object. + /// + /// + /// The object to insert. + /// + /// + /// The number of rows modified. + /// + public int InsertOrReplace(object obj) + { + if (obj == null) + { + return 0; + } + return Insert(obj, "OR REPLACE", obj.GetType()); + } + + /// + /// Inserts all specified objects. + /// For each insertion, if a UNIQUE + /// constraint violation occurs with + /// some pre-existing object, this function + /// deletes the old object. + /// + /// + /// An of the objects to insert or replace. + /// + /// + /// The total number of rows modified. + /// + public int InsertOrReplaceAll(IEnumerable objects) + { + int c = 0; + RunInTransaction(() => + { + foreach (object r in objects) + { + c += InsertOrReplace(r); + } + }); + return c; + } + + /// + /// Inserts the given object and retrieves its + /// auto incremented primary key if it has one. + /// + /// + /// The object to insert. + /// + /// + /// The type of object to insert. + /// + /// + /// The number of rows added to the table. + /// + public int Insert(object obj, Type objType) + { + return Insert(obj, "", objType); + } + + /// + /// Inserts the given object and retrieves its + /// auto incremented primary key if it has one. + /// If a UNIQUE constraint violation occurs with + /// some pre-existing object, this function deletes + /// the old object. + /// + /// + /// The object to insert. + /// + /// + /// The type of object to insert. + /// + /// + /// The number of rows modified. + /// + public int InsertOrReplace(object obj, Type objType) + { + return Insert(obj, "OR REPLACE", objType); + } + + /// + /// Inserts all specified objects. + /// For each insertion, if a UNIQUE + /// constraint violation occurs with + /// some pre-existing object, this function + /// deletes the old object. + /// + /// + /// An of the objects to insert or replace. + /// + /// + /// The type of objects to insert or replace. + /// + /// + /// The total number of rows modified. + /// + public int InsertOrReplaceAll(IEnumerable objects, Type objType) + { + int c = 0; + RunInTransaction(() => + { + foreach (object r in objects) + { + c += InsertOrReplace(r, objType); + } + }); + return c; + } + + /// + /// Inserts the given object and retrieves its + /// auto incremented primary key if it has one. + /// + /// + /// The object to insert. + /// + /// + /// Literal SQL code that gets placed into the command. INSERT {extra} INTO ... + /// + /// + /// The number of rows added to the table. + /// + public int Insert(object obj, string extra) + { + if (obj == null) + { + return 0; + } + return Insert(obj, extra, obj.GetType()); + } + + /// + /// Inserts the given object and retrieves its + /// auto incremented primary key if it has one. + /// + /// + /// The object to insert. + /// + /// + /// Literal SQL code that gets placed into the command. INSERT {extra} INTO ... + /// + /// + /// The type of object to insert. + /// + /// + /// The number of rows added to the table. + /// + public int Insert(object obj, string extra, Type objType) + { + if (obj == null || objType == null) + { + return 0; + } + + + TableMapping map = GetMapping(objType); + + if (map.PK != null && map.PK.IsAutoGuid) + { + PropertyInfo prop = objType.GetRuntimeProperty(map.PK.PropertyName); + if (prop != null) + { + if (prop.GetValue(obj, null).Equals(Guid.Empty)) + { + prop.SetValue(obj, Guid.NewGuid(), null); + } + } + } + + bool replacing = string.Compare(extra, "OR REPLACE", StringComparison.OrdinalIgnoreCase) == 0; + + TableMapping.Column[] cols = replacing ? map.InsertOrReplaceColumns : map.InsertColumns; + var vals = new object[cols.Length]; + for (int i = 0; i < vals.Length; i++) + { + vals[i] = cols[i].GetValue(obj); + } + + PreparedSqlLiteInsertCommand insertCmd = map.GetInsertCommand(this, extra); + int count; + try + { + count = insertCmd.ExecuteNonQuery(vals); + } + catch (SQLiteException ex) + { + if (Platform.SQLiteApi.ExtendedErrCode(this.Handle) == ExtendedResult.ConstraintNotNull) + { + throw NotNullConstraintViolationException.New(ex.Result, ex.Message, map, obj); + } + throw; + } + + if (map.HasAutoIncPK) + { + long id = Platform.SQLiteApi.LastInsertRowid(Handle); + map.SetAutoIncPK(obj, id); + } + + return count; + } + + /// + /// Updates all of the columns of a table using the specified object + /// except for its primary key. + /// The object is required to have a primary key. + /// + /// + /// The object to update. It must have a primary key designated using the PrimaryKeyAttribute. + /// + /// + /// The number of rows updated. + /// + public int Update(object obj) + { + if (obj == null) + { + return 0; + } + return Update(obj, obj.GetType()); + } + + /// + /// Updates all of the columns of a table using the specified object + /// except for its primary key. + /// The object is required to have a primary key. + /// + /// + /// The object to update. It must have a primary key designated using the PrimaryKeyAttribute. + /// + /// + /// The type of object to insert. + /// + /// + /// The number of rows updated. + /// + public int Update(object obj, Type objType) + { + int rowsAffected = 0; + if (obj == null || objType == null) + { + return 0; + } + + TableMapping map = GetMapping(objType); + + TableMapping.Column pk = map.PK; + + if (pk == null) + { + throw new NotSupportedException("Cannot update " + map.TableName + ": it has no PK"); + } + + IEnumerable cols = from p in map.Columns + where p != pk + select p; + IEnumerable vals = from c in cols + select c.GetValue(obj); + var ps = new List(vals); + ps.Add(pk.GetValue(obj)); + string q = string.Format("update \"{0}\" set {1} where {2} = ? ", map.TableName, + string.Join(",", (from c in cols + select "\"" + c.Name + "\" = ? ").ToArray()), pk.Name); + try + { + rowsAffected = Execute(q, ps.ToArray()); + } + catch (SQLiteException ex) + { + if (ex.Result == Result.Constraint && Platform.SQLiteApi.ExtendedErrCode(Handle) == ExtendedResult.ConstraintNotNull) + { + throw NotNullConstraintViolationException.New(ex, map, obj); + } + + throw ex; + } + + return rowsAffected; + } + + /// + /// Updates all specified objects. + /// + /// + /// An of the objects to insert. + /// + /// + /// The number of rows modified. + /// + public int UpdateAll(IEnumerable objects) + { + int c = 0; + RunInTransaction(() => + { + foreach (object r in objects) + { + c += Update(r); + } + }); + return c; + } + + /// + /// Deletes the given object from the database using its primary key. + /// + /// + /// The object to delete. It must have a primary key designated using the PrimaryKeyAttribute. + /// + /// + /// The number of rows deleted. + /// + public int Delete(object objectToDelete) + { + TableMapping map = GetMapping(objectToDelete.GetType()); + TableMapping.Column pk = map.PK; + if (pk == null) + { + throw new NotSupportedException("Cannot delete " + map.TableName + ": it has no PK"); + } + string q = string.Format("delete from \"{0}\" where \"{1}\" = ?", map.TableName, pk.Name); + return Execute(q, pk.GetValue(objectToDelete)); + } + + /// + /// Deletes the object with the specified primary key. + /// + /// + /// The primary key of the object to delete. + /// + /// + /// The number of objects deleted. + /// + /// + /// The type of object. + /// + public int Delete(object primaryKey) + { + TableMapping map = GetMapping(typeof(T)); + TableMapping.Column pk = map.PK; + if (pk == null) + { + throw new NotSupportedException("Cannot delete " + map.TableName + ": it has no PK"); + } + string q = string.Format("delete from \"{0}\" where \"{1}\" = ?", map.TableName, pk.Name); + return Execute(q, primaryKey); + } + + /// + /// Deletes all the objects from the specified table. + /// WARNING WARNING: Let me repeat. It deletes ALL the objects from the + /// specified table. Do you really want to do that? + /// + /// + /// The number of objects deleted. + /// + /// + /// The type of objects to delete. + /// + public int DeleteAll() + { + TableMapping map = GetMapping(typeof(T)); + string query = string.Format("delete from \"{0}\"", map.TableName); + return Execute(query); + } + + ~SQLiteConnection() + { + Dispose(false); + } + + protected virtual void Dispose(bool disposing) + { + Close(); + } + + public void Close() + { + if (_open && Handle != NullHandle) + { + try + { + if (_mappings != null) + { + foreach (TableMapping sqlInsertCommand in _mappings.Values) + { + sqlInsertCommand.Dispose(); + } + } + Result r = Platform.SQLiteApi.Close(Handle); + if (r != Result.OK) + { + string msg = Platform.SQLiteApi.Errmsg16(Handle); + throw SQLiteException.New(r, msg); + } + } + finally + { + Handle = NullHandle; + _open = false; + } + } + } + + public class ColumnInfo + { + // public int cid { get; set; } + + [Column("name")] + public string Name { get; set; } + + // [Column ("type")] + // public string ColumnType { get; set; } + + public int notnull { get; set; } + + // public string dflt_value { get; set; } + + // public int pk { get; set; } + + public override string ToString() + { + return Name; + } + } + + private struct IndexInfo + { + public List Columns; + public string IndexName; + public string TableName; + public bool Unique; + } + + private struct IndexedColumn + { + public string ColumnName; + public int Order; + } + } +} diff --git a/src/SQLite.Net/SQLiteConnectionPool.cs b/src/SQLite.Net/SQLiteConnectionPool.cs new file mode 100644 index 000000000..351d3039c --- /dev/null +++ b/src/SQLite.Net/SQLiteConnectionPool.cs @@ -0,0 +1,99 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System.Collections.Generic; +using SQLite.Net.Interop; + +namespace SQLite.Net +{ + public class SQLiteConnectionPool + { + private readonly Dictionary _entries = new Dictionary(); + private readonly object _entriesLock = new object(); + private readonly ISQLitePlatform _sqlitePlatform; + + public SQLiteConnectionPool(ISQLitePlatform sqlitePlatform) + { + _sqlitePlatform = sqlitePlatform; + } + + public SQLiteConnectionWithLock GetConnection(SQLiteConnectionString connectionString) + { + lock (_entriesLock) + { + Entry entry; + string key = connectionString.ConnectionString; + + if (!_entries.TryGetValue(key, out entry)) + { + entry = new Entry(_sqlitePlatform, connectionString); + _entries[key] = entry; + } + + return entry.Connection; + } + } + + /// + /// Closes all connections managed by this pool. + /// + public void Reset() + { + lock (_entriesLock) + { + foreach (Entry entry in _entries.Values) + { + entry.OnApplicationSuspended(); + } + _entries.Clear(); + } + } + + /// + /// Call this method when the application is suspended. + /// + /// Behaviour here is to close any open connections. + public void ApplicationSuspended() + { + Reset(); + } + + private class Entry + { + public Entry(ISQLitePlatform sqlitePlatform, SQLiteConnectionString connectionString) + { + ConnectionString = connectionString; + Connection = new SQLiteConnectionWithLock(sqlitePlatform, connectionString); + } + + public SQLiteConnectionString ConnectionString { get; private set; } + public SQLiteConnectionWithLock Connection { get; private set; } + + public void OnApplicationSuspended() + { + Connection.Dispose(); + Connection = null; + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/SQLiteConnectionString.cs b/src/SQLite.Net/SQLiteConnectionString.cs new file mode 100644 index 000000000..36a0e4243 --- /dev/null +++ b/src/SQLite.Net/SQLiteConnectionString.cs @@ -0,0 +1,46 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +namespace SQLite.Net +{ + /// + /// Represents a parsed connection string. + /// + public class SQLiteConnectionString + { + public SQLiteConnectionString(string databasePath, bool storeDateTimeAsTicks, + IBlobSerializer serializer = null) + { + ConnectionString = databasePath; + StoreDateTimeAsTicks = storeDateTimeAsTicks; + + DatabasePath = databasePath; + Serializer = serializer; + } + + public string ConnectionString { get; private set; } + public string DatabasePath { get; private set; } + public bool StoreDateTimeAsTicks { get; private set; } + public IBlobSerializer Serializer { get; private set; } + } +} diff --git a/src/SQLite.Net/SQLiteConnectionWithLock.cs b/src/SQLite.Net/SQLiteConnectionWithLock.cs new file mode 100644 index 000000000..6e8805d50 --- /dev/null +++ b/src/SQLite.Net/SQLiteConnectionWithLock.cs @@ -0,0 +1,59 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Threading; +using SQLite.Net.Interop; + +namespace SQLite.Net +{ + public class SQLiteConnectionWithLock : SQLiteConnection + { + private readonly object _lockPoint = new object(); + + public SQLiteConnectionWithLock(ISQLitePlatform sqlitePlatform, SQLiteConnectionString connectionString) + : base(sqlitePlatform, connectionString.DatabasePath, connectionString.StoreDateTimeAsTicks, connectionString.Serializer) + { + } + + public IDisposable Lock() + { + return new LockWrapper(_lockPoint); + } + + private class LockWrapper : IDisposable + { + private readonly object _lockPoint; + + public LockWrapper(object lockPoint) + { + _lockPoint = lockPoint; + Monitor.Enter(_lockPoint); + } + + public void Dispose() + { + Monitor.Exit(_lockPoint); + } + } + } +} diff --git a/src/SQLite.Net/SQLiteException.cs b/src/SQLite.Net/SQLiteException.cs new file mode 100644 index 000000000..94d722f47 --- /dev/null +++ b/src/SQLite.Net/SQLiteException.cs @@ -0,0 +1,42 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using SQLite.Net.Interop; + +namespace SQLite.Net +{ + public class SQLiteException : Exception + { + protected SQLiteException(Result r, string message) : base(message) + { + Result = r; + } + + public Result Result { get; private set; } + + public static SQLiteException New(Result r, string message) + { + return new SQLiteException(r, message); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/TableMapping.cs b/src/SQLite.Net/TableMapping.cs new file mode 100644 index 000000000..7bff511db --- /dev/null +++ b/src/SQLite.Net/TableMapping.cs @@ -0,0 +1,304 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; + +namespace SQLite.Net +{ + public class TableMapping + { + private readonly Column _autoPk; + private readonly ISQLitePlatform _sqlitePlatform; + private Column[] _insertColumns; + private PreparedSqlLiteInsertCommand _insertCommand; + private string _insertCommandExtra; + private Column[] _insertOrReplaceColumns; + + public TableMapping(ISQLitePlatform platformImplementation, Type type, + CreateFlags createFlags = CreateFlags.None) + { + _sqlitePlatform = platformImplementation; + MappedType = type; + + var tableAttr = type.GetTypeInfo().CustomAttributes.FirstOrDefault(data => data.AttributeType == typeof(TableAttribute)); + + TableName = tableAttr != null ? (string)tableAttr.ConstructorArguments.FirstOrDefault().Value : MappedType.Name; + + IEnumerable props = _sqlitePlatform.ReflectionService.GetPublicInstanceProperties(MappedType); + + var cols = new List(); + foreach (PropertyInfo p in props) + { + bool ignore = p.GetCustomAttributes(true).Any(); + + if (p.CanWrite && !ignore) + { + cols.Add(new Column(p, createFlags)); + } + } + Columns = cols.ToArray(); + foreach (Column c in Columns) + { + if (c.IsAutoInc && c.IsPK) + { + _autoPk = c; + } + if (c.IsPK) + { + PK = c; + } + } + + HasAutoIncPK = _autoPk != null; + + if (PK != null) + { + GetByPrimaryKeySql = string.Format("select * from \"{0}\" where \"{1}\" = ?", TableName, PK.Name); + } + else + { + // People should not be calling Get/Find without a PK + GetByPrimaryKeySql = string.Format("select * from \"{0}\" limit 1", TableName); + } + } + + public Type MappedType { get; private set; } + + public string TableName { get; private set; } + + public Column[] Columns { get; private set; } + + public Column PK { get; private set; } + + public string GetByPrimaryKeySql { get; private set; } + + public bool HasAutoIncPK { get; private set; } + + public Column[] InsertColumns + { + get + { + if (_insertColumns == null) + { + _insertColumns = Columns.Where(c => !c.IsAutoInc).ToArray(); + } + return _insertColumns; + } + } + + public Column[] InsertOrReplaceColumns + { + get + { + if (_insertOrReplaceColumns == null) + { + _insertOrReplaceColumns = Columns.ToArray(); + } + return _insertOrReplaceColumns; + } + } + + public void SetAutoIncPK(object obj, long id) + { + if (_autoPk != null) + { + _autoPk.SetValue(obj, Convert.ChangeType(id, _autoPk.ColumnType, null)); + } + } + + public Column FindColumnWithPropertyName(string propertyName) + { + Column exact = Columns.FirstOrDefault(c => c.PropertyName == propertyName); + return exact; + } + + public Column FindColumn(string columnName) + { + Column exact = Columns.FirstOrDefault(c => c.Name == columnName); + return exact; + } + + public PreparedSqlLiteInsertCommand GetInsertCommand(SQLiteConnection conn, string extra) + { + if (_insertCommand == null) + { + _insertCommand = CreateInsertCommand(conn, extra); + _insertCommandExtra = extra; + } + else if (_insertCommandExtra != extra) + { + _insertCommand.Dispose(); + _insertCommand = CreateInsertCommand(conn, extra); + _insertCommandExtra = extra; + } + return _insertCommand; + } + + private PreparedSqlLiteInsertCommand CreateInsertCommand(SQLiteConnection conn, string extra) + { + Column[] cols = InsertColumns; + string insertSql; + if (!cols.Any() && Columns.Count() == 1 && Columns[0].IsAutoInc) + { + insertSql = string.Format("insert {1} into \"{0}\" default values", TableName, extra); + } + else + { + bool replacing = string.Compare(extra, "OR REPLACE", StringComparison.OrdinalIgnoreCase) == 0; + + if (replacing) + { + cols = InsertOrReplaceColumns; + } + + insertSql = string.Format("insert {3} into \"{0}\"({1}) values ({2})", TableName, + string.Join(",", (from c in cols + select "\"" + c.Name + "\"").ToArray()), + string.Join(",", (from c in cols + select "?").ToArray()), extra); + } + + var insertCommand = new PreparedSqlLiteInsertCommand(_sqlitePlatform, conn); + insertCommand.CommandText = insertSql; + return insertCommand; + } + + protected internal void Dispose() + { + if (_insertCommand != null) + { + _insertCommand.Dispose(); + _insertCommand = null; + } + } + + public class Column + { + private readonly PropertyInfo _prop; + + public Column(PropertyInfo prop, CreateFlags createFlags = CreateFlags.None) + { + var colAttr = + prop.GetCustomAttributes(true).FirstOrDefault(); + + _prop = prop; + Name = colAttr == null ? prop.Name : colAttr.Name; + //If this type is Nullable then Nullable.GetUnderlyingType returns the T, otherwise it returns null, so get the actual type instead + ColumnType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType; + Collation = Orm.Collation(prop); + + IsPK = Orm.IsPK(prop) || + (((createFlags & CreateFlags.ImplicitPK) == CreateFlags.ImplicitPK) && + string.Compare(prop.Name, Orm.ImplicitPkName, StringComparison.OrdinalIgnoreCase) == 0); + + bool isAuto = Orm.IsAutoInc(prop) || + (IsPK && ((createFlags & CreateFlags.AutoIncPK) == CreateFlags.AutoIncPK)); + IsAutoGuid = isAuto && ColumnType == typeof(Guid); + IsAutoInc = isAuto && !IsAutoGuid; + + DefaultValue = Orm.GetDefaultValue(prop); + + Indices = Orm.GetIndices(prop); + if (!Indices.Any() + && !IsPK + && ((createFlags & CreateFlags.ImplicitIndex) == CreateFlags.ImplicitIndex) + && Name.EndsWith(Orm.ImplicitIndexSuffix, StringComparison.OrdinalIgnoreCase)) + { + Indices = new[] { new IndexedAttribute() }; + } + IsNullable = !(IsPK || Orm.IsMarkedNotNull(prop)); + MaxStringLength = Orm.MaxStringLength(prop); + } + + public string Name { get; private set; } + + public string PropertyName + { + get { return _prop.Name; } + } + + public Type ColumnType { get; private set; } + + public string Collation { get; private set; } + + public bool IsAutoInc { get; private set; } + + public bool IsAutoGuid { get; private set; } + + public bool IsPK { get; private set; } + + public IEnumerable Indices { get; set; } + + public bool IsNullable { get; private set; } + + public int? MaxStringLength { get; private set; } + public object DefaultValue { get; private set ; } + + /// + /// Set column value. + /// + /// + /// + /// + /// Copied from: http://code.google.com/p/sqlite-net/issues/detail?id=47 + /// + public void SetValue(object obj, object val) + { + Type propType = _prop.PropertyType; + + + + if (propType.GetTypeInfo().IsGenericType && propType.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + Type[] typeCol = propType.GetTypeInfo().GenericTypeArguments; + if (typeCol.Length > 0) + { + Type nullableType = typeCol[0]; + if (nullableType.GetTypeInfo().BaseType == typeof(Enum)) + { + object result = val == null ? null : Enum.Parse(nullableType, val.ToString(), false); + _prop.SetValue(obj, result, null); + } + else + { + _prop.SetValue(obj, val, null); + } + } + } + else + { + _prop.SetValue(obj, val, null); + } + } + + public object GetValue(object obj) + { + return _prop.GetValue(obj, null); + } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/TableQuery.cs b/src/SQLite.Net/TableQuery.cs new file mode 100644 index 000000000..7a43bf238 --- /dev/null +++ b/src/SQLite.Net/TableQuery.cs @@ -0,0 +1,589 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// Copyright (c) 2013 Øystein Krog (oystein.krog@gmail.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using SQLite.Net.Interop; + +namespace SQLite.Net +{ + public class TableQuery : BaseTableQuery, IEnumerable + { + private readonly ISQLitePlatform _sqlitePlatform; + private bool _deferred; + + private BaseTableQuery _joinInner; + private Expression _joinInnerKeySelector; + private BaseTableQuery _joinOuter; + private Expression _joinOuterKeySelector; + private Expression _joinSelector; + private int? _limit; + private int? _offset; + private List _orderBys; + + private Expression _selector; + private Expression _where; + + private TableQuery(ISQLitePlatform platformImplementation, SQLiteConnection conn, TableMapping table) + { + _sqlitePlatform = platformImplementation; + Connection = conn; + Table = table; + } + + public TableQuery(ISQLitePlatform platformImplementation, SQLiteConnection conn) + { + _sqlitePlatform = platformImplementation; + Connection = conn; + Table = Connection.GetMapping(typeof (T)); + } + + public SQLiteConnection Connection { get; private set; } + + public TableMapping Table { get; private set; } + + public IEnumerator GetEnumerator() + { + if (!_deferred) + { + return GenerateCommand("*").ExecuteQuery().GetEnumerator(); + } + + return GenerateCommand("*").ExecuteDeferredQuery().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public TableQuery Clone() + { + var q = new TableQuery(_sqlitePlatform, Connection, Table); + q._where = _where; + q._deferred = _deferred; + if (_orderBys != null) + { + q._orderBys = new List(_orderBys); + } + q._limit = _limit; + q._offset = _offset; + q._joinInner = _joinInner; + q._joinInnerKeySelector = _joinInnerKeySelector; + q._joinOuter = _joinOuter; + q._joinOuterKeySelector = _joinOuterKeySelector; + q._joinSelector = _joinSelector; + q._selector = _selector; + return q; + } + + public TableQuery Where(Expression> predExpr) + { + if (predExpr.NodeType == ExpressionType.Lambda) + { + var lambda = (LambdaExpression) predExpr; + Expression pred = lambda.Body; + TableQuery q = Clone(); + q.AddWhere(pred); + return q; + } + else + { + throw new NotSupportedException("Must be a predicate"); + } + } + + public TableQuery Take(int n) + { + TableQuery q = Clone(); + q._limit = n; + return q; + } + + public TableQuery Skip(int n) + { + TableQuery q = Clone(); + q._offset = n; + return q; + } + + public T ElementAt(int index) + { + return Skip(index).Take(1).First(); + } + + public TableQuery Deferred() + { + TableQuery q = Clone(); + q._deferred = true; + return q; + } + + public TableQuery OrderBy(Expression> orderExpr) + { + return AddOrderBy(orderExpr, true); + } + + public TableQuery OrderByDescending(Expression> orderExpr) + { + return AddOrderBy(orderExpr, false); + } + + public TableQuery ThenBy(Expression> orderExpr) + { + return AddOrderBy(orderExpr, true); + } + + public TableQuery ThenByDescending(Expression> orderExpr) + { + return AddOrderBy(orderExpr, false); + } + + private TableQuery AddOrderBy(Expression> orderExpr, bool asc) + { + if (orderExpr.NodeType == ExpressionType.Lambda) + { + var lambda = (LambdaExpression) orderExpr; + + MemberExpression mem = null; + + var unary = lambda.Body as UnaryExpression; + if (unary != null && unary.NodeType == ExpressionType.Convert) + { + mem = unary.Operand as MemberExpression; + } + else + { + mem = lambda.Body as MemberExpression; + } + + if (mem != null && (mem.Expression.NodeType == ExpressionType.Parameter)) + { + TableQuery q = Clone(); + if (q._orderBys == null) + { + q._orderBys = new List(); + } + q._orderBys.Add(new Ordering + { + ColumnName = Table.FindColumnWithPropertyName(mem.Member.Name).Name, + Ascending = asc + }); + return q; + } + else + { + throw new NotSupportedException("Order By does not support: " + orderExpr); + } + } + else + { + throw new NotSupportedException("Must be a predicate"); + } + } + + private void AddWhere(Expression pred) + { + if (_where == null) + { + _where = pred; + } + else + { + _where = Expression.AndAlso(_where, pred); + } + } + + public TableQuery Join( + TableQuery inner, + Expression> outerKeySelector, + Expression> innerKeySelector, + Expression> resultSelector) + { + var q = new TableQuery(_sqlitePlatform, Connection, Connection.GetMapping(typeof (TResult))) + { + _joinOuter = this, + _joinOuterKeySelector = outerKeySelector, + _joinInner = inner, + _joinInnerKeySelector = innerKeySelector, + _joinSelector = resultSelector, + }; + return q; + } + + public TableQuery Select(Expression> selector) + { + TableQuery q = Clone(); + q._selector = selector; + return q; + } + + private SQLiteCommand GenerateCommand(string selectionList) + { + if (_joinInner != null && _joinOuter != null) + { + throw new NotSupportedException("Joins are not supported."); + } + else + { + string cmdText = "select " + selectionList + " from \"" + Table.TableName + "\""; + var args = new List(); + if (_where != null) + { + CompileResult w = CompileExpr(_where, args); + cmdText += " where " + w.CommandText; + } + if ((_orderBys != null) && (_orderBys.Count > 0)) + { + string t = string.Join(", ", + _orderBys.Select(o => "\"" + o.ColumnName + "\"" + (o.Ascending ? "" : " desc")).ToArray()); + cmdText += " order by " + t; + } + if (_limit.HasValue) + { + cmdText += " limit " + _limit.Value; + } + if (_offset.HasValue) + { + if (!_limit.HasValue) + { + cmdText += " limit -1 "; + } + cmdText += " offset " + _offset.Value; + } + return Connection.CreateCommand(cmdText, args.ToArray()); + } + } + + private CompileResult CompileExpr(Expression expr, List queryArgs) + { + if (expr == null) + { + throw new NotSupportedException("Expression is NULL"); + } + else if (expr is BinaryExpression) + { + var bin = (BinaryExpression) expr; + + CompileResult leftr = CompileExpr(bin.Left, queryArgs); + CompileResult rightr = CompileExpr(bin.Right, queryArgs); + + //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null") + string text; + if (leftr.CommandText == "?" && leftr.Value == null) + { + text = CompileNullBinaryExpression(bin, rightr); + } + else if (rightr.CommandText == "?" && rightr.Value == null) + { + text = CompileNullBinaryExpression(bin, leftr); + } + else + { + text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")"; + } + return new CompileResult + { + CommandText = text + }; + } + else if (expr.NodeType == ExpressionType.Call) + { + var call = (MethodCallExpression) expr; + var args = new CompileResult[call.Arguments.Count]; + CompileResult obj = call.Object != null ? CompileExpr(call.Object, queryArgs) : null; + + for (int i = 0; i < args.Length; i++) + { + args[i] = CompileExpr(call.Arguments[i], queryArgs); + } + + string sqlCall = ""; + + if (call.Method.Name == "Like" && args.Length == 2) + { + sqlCall = "(" + args[0].CommandText + " like " + args[1].CommandText + ")"; + } + else if (call.Method.Name == "Contains" && args.Length == 2) + { + sqlCall = "(" + args[1].CommandText + " in " + args[0].CommandText + ")"; + } + else if (call.Method.Name == "Contains" && args.Length == 1) + { + if (call.Object != null && call.Object.Type == typeof (string)) + { + sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + " || '%'))"; + } + else + { + sqlCall = "(" + args[0].CommandText + " in " + obj.CommandText + ")"; + } + } + else if (call.Method.Name == "StartsWith" && args.Length == 1) + { + sqlCall = "(" + obj.CommandText + " like (" + args[0].CommandText + " || '%'))"; + } + else if (call.Method.Name == "EndsWith" && args.Length == 1) + { + sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + "))"; + } + else if (call.Method.Name == "Equals" && args.Length == 1) + { + sqlCall = "(" + obj.CommandText + " = (" + args[0].CommandText + "))"; + } + else if (call.Method.Name == "ToLower") + { + sqlCall = "(lower(" + obj.CommandText + "))"; + } + else if (call.Method.Name == "ToUpper") + { + sqlCall = "(upper(" + obj.CommandText + "))"; + } + else + { + sqlCall = call.Method.Name.ToLower() + "(" + + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")"; + } + return new CompileResult + { + CommandText = sqlCall + }; + } + else if (expr.NodeType == ExpressionType.Constant) + { + var c = (ConstantExpression) expr; + queryArgs.Add(c.Value); + return new CompileResult + { + CommandText = "?", + Value = c.Value + }; + } + else if (expr.NodeType == ExpressionType.Convert) + { + var u = (UnaryExpression) expr; + Type ty = u.Type; + CompileResult valr = CompileExpr(u.Operand, queryArgs); + return new CompileResult + { + CommandText = valr.CommandText, + Value = valr.Value != null ? ConvertTo(valr.Value, ty) : null + }; + } + else if (expr.NodeType == ExpressionType.MemberAccess) + { + var mem = (MemberExpression) expr; + + if (mem.Expression != null && mem.Expression.NodeType == ExpressionType.Parameter) + { + // + // This is a column of our table, output just the column name + // Need to translate it if that column name is mapped + // + string columnName = Table.FindColumnWithPropertyName(mem.Member.Name).Name; + return new CompileResult + { + CommandText = "\"" + columnName + "\"" + }; + } + else + { + object obj = null; + if (mem.Expression != null) + { + CompileResult r = CompileExpr(mem.Expression, queryArgs); + if (r.Value == null) + { + throw new NotSupportedException("Member access failed to compile expression"); + } + if (r.CommandText == "?") + { + queryArgs.RemoveAt(queryArgs.Count - 1); + } + obj = r.Value; + } + + // + // Get the member value + // + object val = _sqlitePlatform.ReflectionService.GetMemberValue(obj, expr, mem.Member); + + // + // Work special magic for enumerables + // + if (val != null && val is System.Collections.IEnumerable && !(val is string) && !(val is System.Collections.Generic.IEnumerable)) + { + var sb = new StringBuilder(); + sb.Append("("); + string head = ""; + foreach (object a in (IEnumerable) val) + { + queryArgs.Add(a); + sb.Append(head); + sb.Append("?"); + head = ","; + } + sb.Append(")"); + return new CompileResult + { + CommandText = sb.ToString(), + Value = val + }; + } + else + { + queryArgs.Add(val); + return new CompileResult + { + CommandText = "?", + Value = val + }; + } + } + } + throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString()); + } + + private object ConvertTo(object obj, Type t) + { + Type nut = Nullable.GetUnderlyingType(t); + + if (nut != null) + { + if (obj == null) + { + return null; + } + return Convert.ChangeType(obj, nut, CultureInfo.CurrentCulture); + } + else + { + return Convert.ChangeType(obj, t, CultureInfo.CurrentCulture); + } + } + + /// + /// Compiles a BinaryExpression where one of the parameters is null. + /// + /// + /// The non-null parameter + private string CompileNullBinaryExpression(BinaryExpression expression, CompileResult parameter) + { + if (expression.NodeType == ExpressionType.Equal) + { + return "(" + parameter.CommandText + " is ?)"; + } + else if (expression.NodeType == ExpressionType.NotEqual) + { + return "(" + parameter.CommandText + " is not ?)"; + } + else + { + throw new NotSupportedException("Cannot compile Null-BinaryExpression with type " + + expression.NodeType.ToString()); + } + } + + private string GetSqlName(Expression expr) + { + ExpressionType n = expr.NodeType; + if (n == ExpressionType.GreaterThan) + { + return ">"; + } + else if (n == ExpressionType.GreaterThanOrEqual) + { + return ">="; + } + else if (n == ExpressionType.LessThan) + { + return "<"; + } + else if (n == ExpressionType.LessThanOrEqual) + { + return "<="; + } + else if (n == ExpressionType.And) + { + return "&"; + } + else if (n == ExpressionType.AndAlso) + { + return "and"; + } + else if (n == ExpressionType.Or) + { + return "|"; + } + else if (n == ExpressionType.OrElse) + { + return "or"; + } + else if (n == ExpressionType.Equal) + { + return "="; + } + else if (n == ExpressionType.NotEqual) + { + return "!="; + } + else + { + throw new NotSupportedException("Cannot get SQL for: " + n); + } + } + + public int Count() + { + return GenerateCommand("count(*)").ExecuteScalar(); + } + + public int Count(Expression> predExpr) + { + return Where(predExpr).Count(); + } + + public T First() + { + TableQuery query = Take(1); + return query.ToList().First(); + } + + public T FirstOrDefault() + { + TableQuery query = Take(1); + return query.ToList().FirstOrDefault(); + } + + private class CompileResult + { + public string CommandText { get; set; } + + public object Value { get; set; } + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net/TraceListenerExtensions.cs b/src/SQLite.Net/TraceListenerExtensions.cs new file mode 100644 index 000000000..f8f3dcb61 --- /dev/null +++ b/src/SQLite.Net/TraceListenerExtensions.cs @@ -0,0 +1,47 @@ +using System.Globalization; + +namespace SQLite.Net +{ + public static class TraceListenerExtensions + { + public static void WriteLine(this ITraceListener @this, string message) + { + if (@this == null) + { + return; + } + + @this.Receive(message); + } + + public static void WriteLine(this ITraceListener @this, string format, object arg1) + { + if (@this == null) + { + return; + } + + @this.Receive(string.Format(CultureInfo.InvariantCulture, format, arg1)); + } + + public static void WriteLine(this ITraceListener @this, string format, object arg1, object arg2) + { + if (@this == null) + { + return; + } + + @this.Receive(string.Format(CultureInfo.InvariantCulture, format, arg1, arg2)); + } + + public static void WriteLine(this ITraceListener @this, string format, params object[] args) + { + if (@this == null) + { + return; + } + + @this.Receive(string.Format(CultureInfo.InvariantCulture, format, args)); + } + } +} \ No newline at end of file diff --git a/src/SQLite.cs b/src/SQLite.cs deleted file mode 100644 index 5bd252d41..000000000 --- a/src/SQLite.cs +++ /dev/null @@ -1,3060 +0,0 @@ -// -// Copyright (c) 2009-2012 Krueger Systems, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -#if WINDOWS_PHONE && !USE_WP8_NATIVE_SQLITE -#define USE_CSHARP_SQLITE -#endif - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Collections.Generic; -using System.Reflection; -using System.Linq; -using System.Linq.Expressions; -using System.Threading; - -#if USE_CSHARP_SQLITE -using Sqlite3 = Community.CsharpSqlite.Sqlite3; -using Sqlite3DatabaseHandle = Community.CsharpSqlite.Sqlite3.sqlite3; -using Sqlite3Statement = Community.CsharpSqlite.Sqlite3.Vdbe; -#elif USE_WP8_NATIVE_SQLITE -using Sqlite3 = Sqlite.Sqlite3; -using Sqlite3DatabaseHandle = Sqlite.Database; -using Sqlite3Statement = Sqlite.Statement; -#else -using Sqlite3DatabaseHandle = System.IntPtr; -using Sqlite3Statement = System.IntPtr; -#endif - -namespace SQLite -{ - public class SQLiteException : Exception - { - public SQLite3.Result Result { get; private set; } - - protected SQLiteException (SQLite3.Result r,string message) : base(message) - { - Result = r; - } - - public static SQLiteException New (SQLite3.Result r, string message) - { - return new SQLiteException (r, message); - } - } - - [Flags] - public enum SQLiteOpenFlags { - ReadOnly = 1, ReadWrite = 2, Create = 4, - NoMutex = 0x8000, FullMutex = 0x10000, - SharedCache = 0x20000, PrivateCache = 0x40000, - ProtectionComplete = 0x00100000, - ProtectionCompleteUnlessOpen = 0x00200000, - ProtectionCompleteUntilFirstUserAuthentication = 0x00300000, - ProtectionNone = 0x00400000 - } - - [Flags] - public enum CreateFlags - { - None = 0, - ImplicitPK = 1, // create a primary key for field called 'Id' (Orm.ImplicitPkName) - ImplicitIndex = 2, // create an index for fields ending in 'Id' (Orm.ImplicitIndexSuffix) - AllImplicit = 3, // do both above - - AutoIncPK = 4 // force PK field to be auto inc - } - - /// - /// Represents an open connection to a SQLite database. - /// - public partial class SQLiteConnection : IDisposable - { - private bool _open; - private TimeSpan _busyTimeout; - private Dictionary _mappings = null; - private Dictionary _tables = null; - private System.Diagnostics.Stopwatch _sw; - private long _elapsedMilliseconds = 0; - - private int _transactionDepth = 0; - private Random _rand = new Random (); - - public Sqlite3DatabaseHandle Handle { get; private set; } - internal static readonly Sqlite3DatabaseHandle NullHandle = default(Sqlite3DatabaseHandle); - - public string DatabasePath { get; private set; } - - public bool TimeExecution { get; set; } - - public bool Trace { get; set; } - - public bool StoreDateTimeAsTicks { get; private set; } - - /// - /// Constructs a new SQLiteConnection and opens a SQLite database specified by databasePath. - /// - /// - /// Specifies the path to the database file. - /// - /// - /// Specifies whether to store DateTime properties as ticks (true) or strings (false). You - /// absolutely do want to store them as Ticks in all new projects. The default of false is - /// only here for backwards compatibility. There is a *significant* speed advantage, with no - /// down sides, when setting storeDateTimeAsTicks = true. - /// - public SQLiteConnection (string databasePath, bool storeDateTimeAsTicks = false) - : this (databasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create, storeDateTimeAsTicks) - { - } - - /// - /// Constructs a new SQLiteConnection and opens a SQLite database specified by databasePath. - /// - /// - /// Specifies the path to the database file. - /// - /// - /// Specifies whether to store DateTime properties as ticks (true) or strings (false). You - /// absolutely do want to store them as Ticks in all new projects. The default of false is - /// only here for backwards compatibility. There is a *significant* speed advantage, with no - /// down sides, when setting storeDateTimeAsTicks = true. - /// - public SQLiteConnection (string databasePath, SQLiteOpenFlags openFlags, bool storeDateTimeAsTicks = false) - { - if (string.IsNullOrEmpty (databasePath)) - throw new ArgumentException ("Must be specified", "databasePath"); - - DatabasePath = databasePath; - -#if NETFX_CORE - SQLite3.SetDirectory(/*temp directory type*/2, Windows.Storage.ApplicationData.Current.TemporaryFolder.Path); -#endif - - Sqlite3DatabaseHandle handle; - -#if SILVERLIGHT || USE_CSHARP_SQLITE - var r = SQLite3.Open (databasePath, out handle, (int)openFlags, IntPtr.Zero); -#else - // open using the byte[] - // in the case where the path may include Unicode - // force open to using UTF-8 using sqlite3_open_v2 - var databasePathAsBytes = GetNullTerminatedUtf8 (DatabasePath); - var r = SQLite3.Open (databasePathAsBytes, out handle, (int) openFlags, IntPtr.Zero); -#endif - - Handle = handle; - if (r != SQLite3.Result.OK) { - throw SQLiteException.New (r, String.Format ("Could not open database file: {0} ({1})", DatabasePath, r)); - } - _open = true; - - StoreDateTimeAsTicks = storeDateTimeAsTicks; - - BusyTimeout = TimeSpan.FromSeconds (0.1); - } - - static SQLiteConnection () - { - if (_preserveDuringLinkMagic) { - var ti = new ColumnInfo (); - ti.Name = "magic"; - } - } - - public void EnableLoadExtension(int onoff) - { - SQLite3.Result r = SQLite3.EnableLoadExtension(Handle, onoff); - if (r != SQLite3.Result.OK) { - string msg = SQLite3.GetErrmsg (Handle); - throw SQLiteException.New (r, msg); - } - } - - static byte[] GetNullTerminatedUtf8 (string s) - { - var utf8Length = System.Text.Encoding.UTF8.GetByteCount (s); - var bytes = new byte [utf8Length + 1]; - utf8Length = System.Text.Encoding.UTF8.GetBytes(s, 0, s.Length, bytes, 0); - return bytes; - } - - /// - /// Used to list some code that we want the MonoTouch linker - /// to see, but that we never want to actually execute. - /// - static bool _preserveDuringLinkMagic; - - /// - /// Sets a busy handler to sleep the specified amount of time when a table is locked. - /// The handler will sleep multiple times until a total time of has accumulated. - /// - public TimeSpan BusyTimeout { - get { return _busyTimeout; } - set { - _busyTimeout = value; - if (Handle != NullHandle) { - SQLite3.BusyTimeout (Handle, (int)_busyTimeout.TotalMilliseconds); - } - } - } - - /// - /// Returns the mappings from types to tables that the connection - /// currently understands. - /// - public IEnumerable TableMappings { - get { - return _tables != null ? _tables.Values : Enumerable.Empty (); - } - } - - /// - /// Retrieves the mapping that is automatically generated for the given type. - /// - /// - /// The type whose mapping to the database is returned. - /// - /// - /// Optional flags allowing implicit PK and indexes based on naming conventions - /// - /// - /// The mapping represents the schema of the columns of the database and contains - /// methods to set and get properties of objects. - /// - public TableMapping GetMapping(Type type, CreateFlags createFlags = CreateFlags.None) - { - if (_mappings == null) { - _mappings = new Dictionary (); - } - TableMapping map; - if (!_mappings.TryGetValue (type.FullName, out map)) { - map = new TableMapping (type, createFlags); - _mappings [type.FullName] = map; - } - return map; - } - - /// - /// Retrieves the mapping that is automatically generated for the given type. - /// - /// - /// The mapping represents the schema of the columns of the database and contains - /// methods to set and get properties of objects. - /// - public TableMapping GetMapping () - { - return GetMapping (typeof (T)); - } - - private struct IndexedColumn - { - public int Order; - public string ColumnName; - } - - private struct IndexInfo - { - public string IndexName; - public string TableName; - public bool Unique; - public List Columns; - } - - /// - /// Executes a "drop table" on the database. This is non-recoverable. - /// - public int DropTable() - { - var map = GetMapping (typeof (T)); - - var query = string.Format("drop table if exists \"{0}\"", map.TableName); - - return Execute (query); - } - - /// - /// Executes a "create table if not exists" on the database. It also - /// creates any specified indexes on the columns of the table. It uses - /// a schema automatically generated from the specified type. You can - /// later access this schema by calling GetMapping. - /// - /// - /// The number of entries added to the database schema. - /// - public int CreateTable(CreateFlags createFlags = CreateFlags.None) - { - return CreateTable(typeof (T), createFlags); - } - - /// - /// Executes a "create table if not exists" on the database. It also - /// creates any specified indexes on the columns of the table. It uses - /// a schema automatically generated from the specified type. You can - /// later access this schema by calling GetMapping. - /// - /// Type to reflect to a database table. - /// Optional flags allowing implicit PK and indexes based on naming conventions. - /// - /// The number of entries added to the database schema. - /// - public int CreateTable(Type ty, CreateFlags createFlags = CreateFlags.None) - { - if (_tables == null) { - _tables = new Dictionary (); - } - TableMapping map; - if (!_tables.TryGetValue (ty.FullName, out map)) { - map = GetMapping (ty, createFlags); - _tables.Add (ty.FullName, map); - } - var query = "create table if not exists \"" + map.TableName + "\"(\n"; - - var decls = map.Columns.Select (p => Orm.SqlDecl (p, StoreDateTimeAsTicks)); - var decl = string.Join (",\n", decls.ToArray ()); - query += decl; - query += ")"; - - var count = Execute (query); - - if (count == 0) { //Possible bug: This always seems to return 0? - // Table already exists, migrate it - MigrateTable (map); - } - - var indexes = new Dictionary (); - foreach (var c in map.Columns) { - foreach (var i in c.Indices) { - var iname = i.Name ?? map.TableName + "_" + c.Name; - IndexInfo iinfo; - if (!indexes.TryGetValue (iname, out iinfo)) { - iinfo = new IndexInfo { - IndexName = iname, - TableName = map.TableName, - Unique = i.Unique, - Columns = new List () - }; - indexes.Add (iname, iinfo); - } - - if (i.Unique != iinfo.Unique) - throw new Exception ("All the columns in an index must have the same value for their Unique property"); - - iinfo.Columns.Add (new IndexedColumn { - Order = i.Order, - ColumnName = c.Name - }); - } - } - - foreach (var indexName in indexes.Keys) { - var index = indexes[indexName]; - var columns = String.Join("\",\"", index.Columns.OrderBy(i => i.Order).Select(i => i.ColumnName).ToArray()); - count += CreateIndex(indexName, index.TableName, columns, index.Unique); - } - - return count; - } - - /// - /// Creates an index for the specified table and column. - /// - /// Name of the index to create - /// Name of the database table - /// Name of the column to index - /// Whether the index should be unique - public int CreateIndex(string indexName, string tableName, string columnName, bool unique = false) - { - const string sqlFormat = "create {2} index if not exists \"{3}\" on \"{0}\"(\"{1}\")"; - var sql = String.Format(sqlFormat, tableName, columnName, unique ? "unique" : "", indexName); - return Execute(sql); - } - - /// - /// Creates an index for the specified table and column. - /// - /// Name of the database table - /// Name of the column to index - /// Whether the index should be unique - public int CreateIndex(string tableName, string columnName, bool unique = false) - { - return CreateIndex(string.Concat(tableName, "_", columnName.Replace("\",\"", "_")), tableName, columnName, unique); - } - - /// - /// Creates an index for the specified object property. - /// e.g. CreateIndex(c => c.Name); - /// - /// Type to reflect to a database table. - /// Property to index - /// Whether the index should be unique - public void CreateIndex(Expression> property, bool unique = false) - { - MemberExpression mx; - if (property.Body.NodeType == ExpressionType.Convert) - { - mx = ((UnaryExpression)property.Body).Operand as MemberExpression; - } - else - { - mx= (property.Body as MemberExpression); - } - var propertyInfo = mx.Member as PropertyInfo; - if (propertyInfo == null) - { - throw new ArgumentException("The lambda expression 'property' should point to a valid Property"); - } - - var propName = propertyInfo.Name; - - var map = GetMapping(); - var colName = map.FindColumnWithPropertyName(propName).Name; - - CreateIndex(map.TableName, colName, unique); - } - - public class ColumnInfo - { -// public int cid { get; set; } - - [Column ("name")] - public string Name { get; set; } - -// [Column ("type")] -// public string ColumnType { get; set; } - -// public int notnull { get; set; } - -// public string dflt_value { get; set; } - -// public int pk { get; set; } - - public override string ToString () - { - return Name; - } - } - - public List GetTableInfo (string tableName) - { - var query = "pragma table_info(\"" + tableName + "\")"; - return Query (query); - } - - void MigrateTable (TableMapping map) - { - var existingCols = GetTableInfo (map.TableName); - - var toBeAdded = new List (); - - foreach (var p in map.Columns) { - var found = false; - foreach (var c in existingCols) { - found = (string.Compare (p.Name, c.Name, StringComparison.OrdinalIgnoreCase) == 0); - if (found) - break; - } - if (!found) { - toBeAdded.Add (p); - } - } - - foreach (var p in toBeAdded) { - var addCol = "alter table \"" + map.TableName + "\" add column " + Orm.SqlDecl (p, StoreDateTimeAsTicks); - Execute (addCol); - } - } - - /// - /// Creates a new SQLiteCommand. Can be overridden to provide a sub-class. - /// - /// - protected virtual SQLiteCommand NewCommand () - { - return new SQLiteCommand (this); - } - - /// - /// Creates a new SQLiteCommand given the command text with arguments. Place a '?' - /// in the command text for each of the arguments. - /// - /// - /// The fully escaped SQL. - /// - /// - /// Arguments to substitute for the occurences of '?' in the command text. - /// - /// - /// A - /// - public SQLiteCommand CreateCommand (string cmdText, params object[] ps) - { - if (!_open) - throw SQLiteException.New (SQLite3.Result.Error, "Cannot create commands from unopened database"); - - var cmd = NewCommand (); - cmd.CommandText = cmdText; - foreach (var o in ps) { - cmd.Bind (o); - } - return cmd; - } - - /// - /// Creates a SQLiteCommand given the command text (SQL) with arguments. Place a '?' - /// in the command text for each of the arguments and then executes that command. - /// Use this method instead of Query when you don't expect rows back. Such cases include - /// INSERTs, UPDATEs, and DELETEs. - /// You can set the Trace or TimeExecution properties of the connection - /// to profile execution. - /// - /// - /// The fully escaped SQL. - /// - /// - /// Arguments to substitute for the occurences of '?' in the query. - /// - /// - /// The number of rows modified in the database as a result of this execution. - /// - public int Execute (string query, params object[] args) - { - var cmd = CreateCommand (query, args); - - if (TimeExecution) { - if (_sw == null) { - _sw = new Stopwatch (); - } - _sw.Reset (); - _sw.Start (); - } - - var r = cmd.ExecuteNonQuery (); - - if (TimeExecution) { - _sw.Stop (); - _elapsedMilliseconds += _sw.ElapsedMilliseconds; - Debug.WriteLine (string.Format ("Finished in {0} ms ({1:0.0} s total)", _sw.ElapsedMilliseconds, _elapsedMilliseconds / 1000.0)); - } - - return r; - } - - public T ExecuteScalar (string query, params object[] args) - { - var cmd = CreateCommand (query, args); - - if (TimeExecution) { - if (_sw == null) { - _sw = new Stopwatch (); - } - _sw.Reset (); - _sw.Start (); - } - - var r = cmd.ExecuteScalar (); - - if (TimeExecution) { - _sw.Stop (); - _elapsedMilliseconds += _sw.ElapsedMilliseconds; - Debug.WriteLine (string.Format ("Finished in {0} ms ({1:0.0} s total)", _sw.ElapsedMilliseconds, _elapsedMilliseconds / 1000.0)); - } - - return r; - } - - /// - /// Creates a SQLiteCommand given the command text (SQL) with arguments. Place a '?' - /// in the command text for each of the arguments and then executes that command. - /// It returns each row of the result using the mapping automatically generated for - /// the given type. - /// - /// - /// The fully escaped SQL. - /// - /// - /// Arguments to substitute for the occurences of '?' in the query. - /// - /// - /// An enumerable with one result for each row returned by the query. - /// - public List Query (string query, params object[] args) where T : new() - { - var cmd = CreateCommand (query, args); - return cmd.ExecuteQuery (); - } - - /// - /// Creates a SQLiteCommand given the command text (SQL) with arguments. Place a '?' - /// in the command text for each of the arguments and then executes that command. - /// It returns each row of the result using the mapping automatically generated for - /// the given type. - /// - /// - /// The fully escaped SQL. - /// - /// - /// Arguments to substitute for the occurences of '?' in the query. - /// - /// - /// An enumerable with one result for each row returned by the query. - /// The enumerator will call sqlite3_step on each call to MoveNext, so the database - /// connection must remain open for the lifetime of the enumerator. - /// - public IEnumerable DeferredQuery(string query, params object[] args) where T : new() - { - var cmd = CreateCommand(query, args); - return cmd.ExecuteDeferredQuery(); - } - - /// - /// Creates a SQLiteCommand given the command text (SQL) with arguments. Place a '?' - /// in the command text for each of the arguments and then executes that command. - /// It returns each row of the result using the specified mapping. This function is - /// only used by libraries in order to query the database via introspection. It is - /// normally not used. - /// - /// - /// A to use to convert the resulting rows - /// into objects. - /// - /// - /// The fully escaped SQL. - /// - /// - /// Arguments to substitute for the occurences of '?' in the query. - /// - /// - /// An enumerable with one result for each row returned by the query. - /// - public List Query (TableMapping map, string query, params object[] args) - { - var cmd = CreateCommand (query, args); - return cmd.ExecuteQuery (map); - } - - /// - /// Creates a SQLiteCommand given the command text (SQL) with arguments. Place a '?' - /// in the command text for each of the arguments and then executes that command. - /// It returns each row of the result using the specified mapping. This function is - /// only used by libraries in order to query the database via introspection. It is - /// normally not used. - /// - /// - /// A to use to convert the resulting rows - /// into objects. - /// - /// - /// The fully escaped SQL. - /// - /// - /// Arguments to substitute for the occurences of '?' in the query. - /// - /// - /// An enumerable with one result for each row returned by the query. - /// The enumerator will call sqlite3_step on each call to MoveNext, so the database - /// connection must remain open for the lifetime of the enumerator. - /// - public IEnumerable DeferredQuery(TableMapping map, string query, params object[] args) - { - var cmd = CreateCommand(query, args); - return cmd.ExecuteDeferredQuery(map); - } - - /// - /// Returns a queryable interface to the table represented by the given type. - /// - /// - /// A queryable object that is able to translate Where, OrderBy, and Take - /// queries into native SQL. - /// - public TableQuery Table () where T : new() - { - return new TableQuery (this); - } - - /// - /// Attempts to retrieve an object with the given primary key from the table - /// associated with the specified type. Use of this method requires that - /// the given type have a designated PrimaryKey (using the PrimaryKeyAttribute). - /// - /// - /// The primary key. - /// - /// - /// The object with the given primary key. Throws a not found exception - /// if the object is not found. - /// - public T Get (object pk) where T : new() - { - var map = GetMapping (typeof(T)); - return Query (map.GetByPrimaryKeySql, pk).First (); - } - - /// - /// Attempts to retrieve the first object that matches the predicate from the table - /// associated with the specified type. - /// - /// - /// A predicate for which object to find. - /// - /// - /// The object that matches the given predicate. Throws a not found exception - /// if the object is not found. - /// - public T Get (Expression> predicate) where T : new() - { - return Table ().Where (predicate).First (); - } - - /// - /// Attempts to retrieve an object with the given primary key from the table - /// associated with the specified type. Use of this method requires that - /// the given type have a designated PrimaryKey (using the PrimaryKeyAttribute). - /// - /// - /// The primary key. - /// - /// - /// The object with the given primary key or null - /// if the object is not found. - /// - public T Find (object pk) where T : new () - { - var map = GetMapping (typeof (T)); - return Query (map.GetByPrimaryKeySql, pk).FirstOrDefault (); - } - - /// - /// Attempts to retrieve an object with the given primary key from the table - /// associated with the specified type. Use of this method requires that - /// the given type have a designated PrimaryKey (using the PrimaryKeyAttribute). - /// - /// - /// The primary key. - /// - /// - /// The TableMapping used to identify the object type. - /// - /// - /// The object with the given primary key or null - /// if the object is not found. - /// - public object Find (object pk, TableMapping map) - { - return Query (map, map.GetByPrimaryKeySql, pk).FirstOrDefault (); - } - - /// - /// Attempts to retrieve the first object that matches the predicate from the table - /// associated with the specified type. - /// - /// - /// A predicate for which object to find. - /// - /// - /// The object that matches the given predicate or null - /// if the object is not found. - /// - public T Find (Expression> predicate) where T : new() - { - return Table ().Where (predicate).FirstOrDefault (); - } - - /// - /// Whether has been called and the database is waiting for a . - /// - public bool IsInTransaction { - get { return _transactionDepth > 0; } - } - - /// - /// Begins a new transaction. Call to end the transaction. - /// - /// Throws if a transaction has already begun. - public void BeginTransaction () - { - // The BEGIN command only works if the transaction stack is empty, - // or in other words if there are no pending transactions. - // If the transaction stack is not empty when the BEGIN command is invoked, - // then the command fails with an error. - // Rather than crash with an error, we will just ignore calls to BeginTransaction - // that would result in an error. - if (Interlocked.CompareExchange (ref _transactionDepth, 1, 0) == 0) { - try { - Execute ("begin transaction"); - } catch (Exception ex) { - var sqlExp = ex as SQLiteException; - if (sqlExp != null) { - // It is recommended that applications respond to the errors listed below - // by explicitly issuing a ROLLBACK command. - // TODO: This rollback failsafe should be localized to all throw sites. - switch (sqlExp.Result) { - case SQLite3.Result.IOError: - case SQLite3.Result.Full: - case SQLite3.Result.Busy: - case SQLite3.Result.NoMem: - case SQLite3.Result.Interrupt: - RollbackTo (null, true); - break; - } - } else { - // Call decrement and not VolatileWrite in case we've already - // created a transaction point in SaveTransactionPoint since the catch. - Interlocked.Decrement (ref _transactionDepth); - } - - throw; - } - } else { - // Calling BeginTransaction on an already open transaction is invalid - throw new InvalidOperationException ("Cannot begin a transaction while already in a transaction."); - } - } - - /// - /// Creates a savepoint in the database at the current point in the transaction timeline. - /// Begins a new transaction if one is not in progress. - /// - /// Call to undo transactions since the returned savepoint. - /// Call to commit transactions after the savepoint returned here. - /// Call to end the transaction, committing all changes. - /// - /// A string naming the savepoint. - public string SaveTransactionPoint () - { - int depth = Interlocked.Increment (ref _transactionDepth) - 1; - string retVal = "S" + _rand.Next (short.MaxValue) + "D" + depth; - - try { - Execute ("savepoint " + retVal); - } catch (Exception ex) { - var sqlExp = ex as SQLiteException; - if (sqlExp != null) { - // It is recommended that applications respond to the errors listed below - // by explicitly issuing a ROLLBACK command. - // TODO: This rollback failsafe should be localized to all throw sites. - switch (sqlExp.Result) { - case SQLite3.Result.IOError: - case SQLite3.Result.Full: - case SQLite3.Result.Busy: - case SQLite3.Result.NoMem: - case SQLite3.Result.Interrupt: - RollbackTo (null, true); - break; - } - } else { - Interlocked.Decrement (ref _transactionDepth); - } - - throw; - } - - return retVal; - } - - /// - /// Rolls back the transaction that was begun by or . - /// - public void Rollback () - { - RollbackTo (null, false); - } - - /// - /// Rolls back the savepoint created by or SaveTransactionPoint. - /// - /// The name of the savepoint to roll back to, as returned by . If savepoint is null or empty, this method is equivalent to a call to - public void RollbackTo (string savepoint) - { - RollbackTo (savepoint, false); - } - - /// - /// Rolls back the transaction that was begun by . - /// - /// true to avoid throwing exceptions, false otherwise - void RollbackTo (string savepoint, bool noThrow) - { - // Rolling back without a TO clause rolls backs all transactions - // and leaves the transaction stack empty. - try { - if (String.IsNullOrEmpty (savepoint)) { - if (Interlocked.Exchange (ref _transactionDepth, 0) > 0) { - Execute ("rollback"); - } - } else { - DoSavePointExecute (savepoint, "rollback to "); - } - } catch (SQLiteException) { - if (!noThrow) - throw; - - } - // No need to rollback if there are no transactions open. - } - - /// - /// Releases a savepoint returned from . Releasing a savepoint - /// makes changes since that savepoint permanent if the savepoint began the transaction, - /// or otherwise the changes are permanent pending a call to . - /// - /// The RELEASE command is like a COMMIT for a SAVEPOINT. - /// - /// The name of the savepoint to release. The string should be the result of a call to - public void Release (string savepoint) - { - DoSavePointExecute (savepoint, "release "); - } - - void DoSavePointExecute (string savepoint, string cmd) - { - // Validate the savepoint - int firstLen = savepoint.IndexOf ('D'); - if (firstLen >= 2 && savepoint.Length > firstLen + 1) { - int depth; - if (Int32.TryParse (savepoint.Substring (firstLen + 1), out depth)) { - // TODO: Mild race here, but inescapable without locking almost everywhere. - if (0 <= depth && depth < _transactionDepth) { -#if NETFX_CORE - Volatile.Write (ref _transactionDepth, depth); -#elif SILVERLIGHT - _transactionDepth = depth; -#else - Thread.VolatileWrite (ref _transactionDepth, depth); -#endif - Execute (cmd + savepoint); - return; - } - } - } - - throw new ArgumentException ("savePoint is not valid, and should be the result of a call to SaveTransactionPoint.", "savePoint"); - } - - /// - /// Commits the transaction that was begun by . - /// - public void Commit () - { - if (Interlocked.Exchange (ref _transactionDepth, 0) != 0) { - Execute ("commit"); - } - // Do nothing on a commit with no open transaction - } - - /// - /// Executes within a (possibly nested) transaction by wrapping it in a SAVEPOINT. If an - /// exception occurs the whole transaction is rolled back, not just the current savepoint. The exception - /// is rethrown. - /// - /// - /// The to perform within a transaction. can contain any number - /// of operations on the connection but should never call or - /// . - /// - public void RunInTransaction (Action action) - { - try { - var savePoint = SaveTransactionPoint (); - action (); - Release (savePoint); - } catch (Exception) { - Rollback (); - throw; - } - } - - /// - /// Inserts all specified objects. - /// - /// - /// An of the objects to insert. - /// - /// - /// The number of rows added to the table. - /// - public int InsertAll (System.Collections.IEnumerable objects) - { - var c = 0; - RunInTransaction(() => { - foreach (var r in objects) { - c += Insert (r); - } - }); - return c; - } - - /// - /// Inserts all specified objects. - /// - /// - /// An of the objects to insert. - /// - /// - /// Literal SQL code that gets placed into the command. INSERT {extra} INTO ... - /// - /// - /// The number of rows added to the table. - /// - public int InsertAll (System.Collections.IEnumerable objects, string extra) - { - var c = 0; - RunInTransaction (() => { - foreach (var r in objects) { - c += Insert (r, extra); - } - }); - return c; - } - - /// - /// Inserts all specified objects. - /// - /// - /// An of the objects to insert. - /// - /// - /// The type of object to insert. - /// - /// - /// The number of rows added to the table. - /// - public int InsertAll (System.Collections.IEnumerable objects, Type objType) - { - var c = 0; - RunInTransaction (() => { - foreach (var r in objects) { - c += Insert (r, objType); - } - }); - return c; - } - - /// - /// Inserts the given object and retrieves its - /// auto incremented primary key if it has one. - /// - /// - /// The object to insert. - /// - /// - /// The number of rows added to the table. - /// - public int Insert (object obj) - { - if (obj == null) { - return 0; - } - return Insert (obj, "", obj.GetType ()); - } - - /// - /// Inserts the given object and retrieves its - /// auto incremented primary key if it has one. - /// If a UNIQUE constraint violation occurs with - /// some pre-existing object, this function deletes - /// the old object. - /// - /// - /// The object to insert. - /// - /// - /// The number of rows modified. - /// - public int InsertOrReplace (object obj) - { - if (obj == null) { - return 0; - } - return Insert (obj, "OR REPLACE", obj.GetType ()); - } - - /// - /// Inserts the given object and retrieves its - /// auto incremented primary key if it has one. - /// - /// - /// The object to insert. - /// - /// - /// The type of object to insert. - /// - /// - /// The number of rows added to the table. - /// - public int Insert (object obj, Type objType) - { - return Insert (obj, "", objType); - } - - /// - /// Inserts the given object and retrieves its - /// auto incremented primary key if it has one. - /// If a UNIQUE constraint violation occurs with - /// some pre-existing object, this function deletes - /// the old object. - /// - /// - /// The object to insert. - /// - /// - /// The type of object to insert. - /// - /// - /// The number of rows modified. - /// - public int InsertOrReplace (object obj, Type objType) - { - return Insert (obj, "OR REPLACE", objType); - } - - /// - /// Inserts the given object and retrieves its - /// auto incremented primary key if it has one. - /// - /// - /// The object to insert. - /// - /// - /// Literal SQL code that gets placed into the command. INSERT {extra} INTO ... - /// - /// - /// The number of rows added to the table. - /// - public int Insert (object obj, string extra) - { - if (obj == null) { - return 0; - } - return Insert (obj, extra, obj.GetType ()); - } - - /// - /// Inserts the given object and retrieves its - /// auto incremented primary key if it has one. - /// - /// - /// The object to insert. - /// - /// - /// Literal SQL code that gets placed into the command. INSERT {extra} INTO ... - /// - /// - /// The type of object to insert. - /// - /// - /// The number of rows added to the table. - /// - public int Insert (object obj, string extra, Type objType) - { - if (obj == null || objType == null) { - return 0; - } - - - var map = GetMapping (objType); - -#if NETFX_CORE - if (map.PK != null && map.PK.IsAutoGuid) - { - // no GetProperty so search our way up the inheritance chain till we find it - PropertyInfo prop; - while (objType != null) - { - var info = objType.GetTypeInfo(); - prop = info.GetDeclaredProperty(map.PK.PropertyName); - if (prop != null) - { - if (prop.GetValue(obj, null).Equals(Guid.Empty)) - { - prop.SetValue(obj, Guid.NewGuid(), null); - } - break; - } - - objType = info.BaseType; - } - } -#else - if (map.PK != null && map.PK.IsAutoGuid) { - var prop = objType.GetProperty(map.PK.PropertyName); - if (prop != null) { - if (prop.GetValue(obj, null).Equals(Guid.Empty)) { - prop.SetValue(obj, Guid.NewGuid(), null); - } - } - } -#endif - - - var replacing = string.Compare (extra, "OR REPLACE", StringComparison.OrdinalIgnoreCase) == 0; - - var cols = replacing ? map.InsertOrReplaceColumns : map.InsertColumns; - var vals = new object[cols.Length]; - for (var i = 0; i < vals.Length; i++) { - vals [i] = cols [i].GetValue (obj); - } - - var insertCmd = map.GetInsertCommand (this, extra); - var count = insertCmd.ExecuteNonQuery (vals); - - if (map.HasAutoIncPK) - { - var id = SQLite3.LastInsertRowid (Handle); - map.SetAutoIncPK (obj, id); - } - - return count; - } - - /// - /// Updates all of the columns of a table using the specified object - /// except for its primary key. - /// The object is required to have a primary key. - /// - /// - /// The object to update. It must have a primary key designated using the PrimaryKeyAttribute. - /// - /// - /// The number of rows updated. - /// - public int Update (object obj) - { - if (obj == null) { - return 0; - } - return Update (obj, obj.GetType ()); - } - - /// - /// Updates all of the columns of a table using the specified object - /// except for its primary key. - /// The object is required to have a primary key. - /// - /// - /// The object to update. It must have a primary key designated using the PrimaryKeyAttribute. - /// - /// - /// The type of object to insert. - /// - /// - /// The number of rows updated. - /// - public int Update (object obj, Type objType) - { - if (obj == null || objType == null) { - return 0; - } - - var map = GetMapping (objType); - - var pk = map.PK; - - if (pk == null) { - throw new NotSupportedException ("Cannot update " + map.TableName + ": it has no PK"); - } - - var cols = from p in map.Columns - where p != pk - select p; - var vals = from c in cols - select c.GetValue (obj); - var ps = new List (vals); - ps.Add (pk.GetValue (obj)); - var q = string.Format ("update \"{0}\" set {1} where {2} = ? ", map.TableName, string.Join (",", (from c in cols - select "\"" + c.Name + "\" = ? ").ToArray ()), pk.Name); - return Execute (q, ps.ToArray ()); - } - - /// - /// Updates all specified objects. - /// - /// - /// An of the objects to insert. - /// - /// - /// The number of rows modified. - /// - public int UpdateAll (System.Collections.IEnumerable objects) - { - var c = 0; - RunInTransaction (() => { - foreach (var r in objects) { - c += Update (r); - } - }); - return c; - } - - /// - /// Deletes the given object from the database using its primary key. - /// - /// - /// The object to delete. It must have a primary key designated using the PrimaryKeyAttribute. - /// - /// - /// The number of rows deleted. - /// - public int Delete (object objectToDelete) - { - var map = GetMapping (objectToDelete.GetType ()); - var pk = map.PK; - if (pk == null) { - throw new NotSupportedException ("Cannot delete " + map.TableName + ": it has no PK"); - } - var q = string.Format ("delete from \"{0}\" where \"{1}\" = ?", map.TableName, pk.Name); - return Execute (q, pk.GetValue (objectToDelete)); - } - - /// - /// Deletes the object with the specified primary key. - /// - /// - /// The primary key of the object to delete. - /// - /// - /// The number of objects deleted. - /// - /// - /// The type of object. - /// - public int Delete (object primaryKey) - { - var map = GetMapping (typeof (T)); - var pk = map.PK; - if (pk == null) { - throw new NotSupportedException ("Cannot delete " + map.TableName + ": it has no PK"); - } - var q = string.Format ("delete from \"{0}\" where \"{1}\" = ?", map.TableName, pk.Name); - return Execute (q, primaryKey); - } - - /// - /// Deletes all the objects from the specified table. - /// WARNING WARNING: Let me repeat. It deletes ALL the objects from the - /// specified table. Do you really want to do that? - /// - /// - /// The number of objects deleted. - /// - /// - /// The type of objects to delete. - /// - public int DeleteAll () - { - var map = GetMapping (typeof (T)); - var query = string.Format("delete from \"{0}\"", map.TableName); - return Execute (query); - } - - ~SQLiteConnection () - { - Dispose (false); - } - - public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - - protected virtual void Dispose (bool disposing) - { - Close (); - } - - public void Close () - { - if (_open && Handle != NullHandle) { - try { - if (_mappings != null) { - foreach (var sqlInsertCommand in _mappings.Values) { - sqlInsertCommand.Dispose(); - } - } - var r = SQLite3.Close (Handle); - if (r != SQLite3.Result.OK) { - string msg = SQLite3.GetErrmsg (Handle); - throw SQLiteException.New (r, msg); - } - } - finally { - Handle = NullHandle; - _open = false; - } - } - } - } - - /// - /// Represents a parsed connection string. - /// - class SQLiteConnectionString - { - public string ConnectionString { get; private set; } - public string DatabasePath { get; private set; } - public bool StoreDateTimeAsTicks { get; private set; } - -#if NETFX_CORE - static readonly string MetroStyleDataPath = Windows.Storage.ApplicationData.Current.LocalFolder.Path; -#endif - - public SQLiteConnectionString (string databasePath, bool storeDateTimeAsTicks) - { - ConnectionString = databasePath; - StoreDateTimeAsTicks = storeDateTimeAsTicks; - -#if NETFX_CORE - DatabasePath = System.IO.Path.Combine (MetroStyleDataPath, databasePath); -#else - DatabasePath = databasePath; -#endif - } - } - - [AttributeUsage (AttributeTargets.Class)] - public class TableAttribute : Attribute - { - public string Name { get; set; } - - public TableAttribute (string name) - { - Name = name; - } - } - - [AttributeUsage (AttributeTargets.Property)] - public class ColumnAttribute : Attribute - { - public string Name { get; set; } - - public ColumnAttribute (string name) - { - Name = name; - } - } - - [AttributeUsage (AttributeTargets.Property)] - public class PrimaryKeyAttribute : Attribute - { - } - - [AttributeUsage (AttributeTargets.Property)] - public class AutoIncrementAttribute : Attribute - { - } - - [AttributeUsage (AttributeTargets.Property)] - public class IndexedAttribute : Attribute - { - public string Name { get; set; } - public int Order { get; set; } - public virtual bool Unique { get; set; } - - public IndexedAttribute() - { - } - - public IndexedAttribute(string name, int order) - { - Name = name; - Order = order; - } - } - - [AttributeUsage (AttributeTargets.Property)] - public class IgnoreAttribute : Attribute - { - } - - [AttributeUsage (AttributeTargets.Property)] - public class UniqueAttribute : IndexedAttribute - { - public override bool Unique { - get { return true; } - set { /* throw? */ } - } - } - - [AttributeUsage (AttributeTargets.Property)] - public class MaxLengthAttribute : Attribute - { - public int Value { get; private set; } - - public MaxLengthAttribute (int length) - { - Value = length; - } - } - - [AttributeUsage (AttributeTargets.Property)] - public class CollationAttribute: Attribute - { - public string Value { get; private set; } - - public CollationAttribute (string collation) - { - Value = collation; - } - } - - public class TableMapping - { - public Type MappedType { get; private set; } - - public string TableName { get; private set; } - - public Column[] Columns { get; private set; } - - public Column PK { get; private set; } - - public string GetByPrimaryKeySql { get; private set; } - - Column _autoPk; - Column[] _insertColumns; - Column[] _insertOrReplaceColumns; - - public TableMapping(Type type, CreateFlags createFlags = CreateFlags.None) - { - MappedType = type; - -#if NETFX_CORE - var tableAttr = (TableAttribute)System.Reflection.CustomAttributeExtensions - .GetCustomAttribute(type.GetTypeInfo(), typeof(TableAttribute), true); -#else - var tableAttr = (TableAttribute)type.GetCustomAttributes (typeof (TableAttribute), true).FirstOrDefault (); -#endif - - TableName = tableAttr != null ? tableAttr.Name : MappedType.Name; - -#if !NETFX_CORE - var props = MappedType.GetProperties (BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); -#else - var props = from p in MappedType.GetRuntimeProperties() - where ((p.GetMethod != null && p.GetMethod.IsPublic) || (p.SetMethod != null && p.SetMethod.IsPublic) || (p.GetMethod != null && p.GetMethod.IsStatic) || (p.SetMethod != null && p.SetMethod.IsStatic)) - select p; -#endif - var cols = new List (); - foreach (var p in props) { -#if !NETFX_CORE - var ignore = p.GetCustomAttributes (typeof(IgnoreAttribute), true).Length > 0; -#else - var ignore = p.GetCustomAttributes (typeof(IgnoreAttribute), true).Count() > 0; -#endif - if (p.CanWrite && !ignore) { - cols.Add (new Column (p, createFlags)); - } - } - Columns = cols.ToArray (); - foreach (var c in Columns) { - if (c.IsAutoInc && c.IsPK) { - _autoPk = c; - } - if (c.IsPK) { - PK = c; - } - } - - HasAutoIncPK = _autoPk != null; - - if (PK != null) { - GetByPrimaryKeySql = string.Format ("select * from \"{0}\" where \"{1}\" = ?", TableName, PK.Name); - } - else { - // People should not be calling Get/Find without a PK - GetByPrimaryKeySql = string.Format ("select * from \"{0}\" limit 1", TableName); - } - } - - public bool HasAutoIncPK { get; private set; } - - public void SetAutoIncPK (object obj, long id) - { - if (_autoPk != null) { - _autoPk.SetValue (obj, Convert.ChangeType (id, _autoPk.ColumnType, null)); - } - } - - public Column[] InsertColumns { - get { - if (_insertColumns == null) { - _insertColumns = Columns.Where (c => !c.IsAutoInc).ToArray (); - } - return _insertColumns; - } - } - - public Column[] InsertOrReplaceColumns { - get { - if (_insertOrReplaceColumns == null) { - _insertOrReplaceColumns = Columns.ToArray (); - } - return _insertOrReplaceColumns; - } - } - - public Column FindColumnWithPropertyName (string propertyName) - { - var exact = Columns.FirstOrDefault (c => c.PropertyName == propertyName); - return exact; - } - - public Column FindColumn (string columnName) - { - var exact = Columns.FirstOrDefault (c => c.Name == columnName); - return exact; - } - - PreparedSqlLiteInsertCommand _insertCommand; - string _insertCommandExtra; - - public PreparedSqlLiteInsertCommand GetInsertCommand(SQLiteConnection conn, string extra) - { - if (_insertCommand == null) { - _insertCommand = CreateInsertCommand(conn, extra); - _insertCommandExtra = extra; - } - else if (_insertCommandExtra != extra) { - _insertCommand.Dispose(); - _insertCommand = CreateInsertCommand(conn, extra); - _insertCommandExtra = extra; - } - return _insertCommand; - } - - PreparedSqlLiteInsertCommand CreateInsertCommand(SQLiteConnection conn, string extra) - { - var cols = InsertColumns; - string insertSql; - if (!cols.Any() && Columns.Count() == 1 && Columns[0].IsAutoInc) - { - insertSql = string.Format("insert {1} into \"{0}\" default values", TableName, extra); - } - else - { - var replacing = string.Compare (extra, "OR REPLACE", StringComparison.OrdinalIgnoreCase) == 0; - - if (replacing) { - cols = InsertOrReplaceColumns; - } - - insertSql = string.Format("insert {3} into \"{0}\"({1}) values ({2})", TableName, - string.Join(",", (from c in cols - select "\"" + c.Name + "\"").ToArray()), - string.Join(",", (from c in cols - select "?").ToArray()), extra); - - } - - var insertCommand = new PreparedSqlLiteInsertCommand(conn); - insertCommand.CommandText = insertSql; - return insertCommand; - } - - protected internal void Dispose() - { - if (_insertCommand != null) { - _insertCommand.Dispose(); - _insertCommand = null; - } - } - - public class Column - { - PropertyInfo _prop; - - public string Name { get; private set; } - - public string PropertyName { get { return _prop.Name; } } - - public Type ColumnType { get; private set; } - - public string Collation { get; private set; } - - public bool IsAutoInc { get; private set; } - public bool IsAutoGuid { get; private set; } - - public bool IsPK { get; private set; } - - public IEnumerable Indices { get; set; } - - public bool IsNullable { get; private set; } - - public int MaxStringLength { get; private set; } - - public Column(PropertyInfo prop, CreateFlags createFlags = CreateFlags.None) - { - var colAttr = (ColumnAttribute)prop.GetCustomAttributes(typeof(ColumnAttribute), true).FirstOrDefault(); - - _prop = prop; - Name = colAttr == null ? prop.Name : colAttr.Name; - //If this type is Nullable then Nullable.GetUnderlyingType returns the T, otherwise it returns null, so get the actual type instead - ColumnType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType; - Collation = Orm.Collation(prop); - - IsPK = Orm.IsPK(prop) || - (((createFlags & CreateFlags.ImplicitPK) == CreateFlags.ImplicitPK) && - string.Compare (prop.Name, Orm.ImplicitPkName, StringComparison.OrdinalIgnoreCase) == 0); - - var isAuto = Orm.IsAutoInc(prop) || (IsPK && ((createFlags & CreateFlags.AutoIncPK) == CreateFlags.AutoIncPK)); - IsAutoGuid = isAuto && ColumnType == typeof(Guid); - IsAutoInc = isAuto && !IsAutoGuid; - - Indices = Orm.GetIndices(prop); - if (!Indices.Any() - && !IsPK - && ((createFlags & CreateFlags.ImplicitIndex) == CreateFlags.ImplicitIndex) - && Name.EndsWith (Orm.ImplicitIndexSuffix, StringComparison.OrdinalIgnoreCase) - ) - { - Indices = new IndexedAttribute[] { new IndexedAttribute() }; - } - IsNullable = !IsPK; - MaxStringLength = Orm.MaxStringLength(prop); - } - - public void SetValue (object obj, object val) - { - _prop.SetValue (obj, val, null); - } - - public object GetValue (object obj) - { - return _prop.GetValue (obj, null); - } - } - } - - public static class Orm - { - public const int DefaultMaxStringLength = 140; - public const string ImplicitPkName = "Id"; - public const string ImplicitIndexSuffix = "Id"; - - public static string SqlDecl (TableMapping.Column p, bool storeDateTimeAsTicks) - { - string decl = "\"" + p.Name + "\" " + SqlType (p, storeDateTimeAsTicks) + " "; - - if (p.IsPK) { - decl += "primary key "; - } - if (p.IsAutoInc) { - decl += "autoincrement "; - } - if (!p.IsNullable) { - decl += "not null "; - } - if (!string.IsNullOrEmpty (p.Collation)) { - decl += "collate " + p.Collation + " "; - } - - return decl; - } - - public static string SqlType (TableMapping.Column p, bool storeDateTimeAsTicks) - { - var clrType = p.ColumnType; - if (clrType == typeof(Boolean) || clrType == typeof(Byte) || clrType == typeof(UInt16) || clrType == typeof(SByte) || clrType == typeof(Int16) || clrType == typeof(Int32)) { - return "integer"; - } else if (clrType == typeof(UInt32) || clrType == typeof(Int64)) { - return "bigint"; - } else if (clrType == typeof(Single) || clrType == typeof(Double) || clrType == typeof(Decimal)) { - return "float"; - } else if (clrType == typeof(String)) { - int len = p.MaxStringLength; - return "varchar(" + len + ")"; - } else if (clrType == typeof(DateTime)) { - return storeDateTimeAsTicks ? "bigint" : "datetime"; -#if !NETFX_CORE - } else if (clrType.IsEnum) { -#else - } else if (clrType.GetTypeInfo().IsEnum) { -#endif - return "integer"; - } else if (clrType == typeof(byte[])) { - return "blob"; - } else if (clrType == typeof(Guid)) { - return "varchar(36)"; - } else { - throw new NotSupportedException ("Don't know about " + clrType); - } - } - - public static bool IsPK (MemberInfo p) - { - var attrs = p.GetCustomAttributes (typeof(PrimaryKeyAttribute), true); -#if !NETFX_CORE - return attrs.Length > 0; -#else - return attrs.Count() > 0; -#endif - } - - public static string Collation (MemberInfo p) - { - var attrs = p.GetCustomAttributes (typeof(CollationAttribute), true); -#if !NETFX_CORE - if (attrs.Length > 0) { - return ((CollationAttribute)attrs [0]).Value; -#else - if (attrs.Count() > 0) { - return ((CollationAttribute)attrs.First()).Value; -#endif - } else { - return string.Empty; - } - } - - public static bool IsAutoInc (MemberInfo p) - { - var attrs = p.GetCustomAttributes (typeof(AutoIncrementAttribute), true); -#if !NETFX_CORE - return attrs.Length > 0; -#else - return attrs.Count() > 0; -#endif - } - - public static IEnumerable GetIndices(MemberInfo p) - { - var attrs = p.GetCustomAttributes(typeof(IndexedAttribute), true); - return attrs.Cast(); - } - - public static int MaxStringLength(PropertyInfo p) - { - var attrs = p.GetCustomAttributes (typeof(MaxLengthAttribute), true); -#if !NETFX_CORE - if (attrs.Length > 0) { - return ((MaxLengthAttribute)attrs [0]).Value; -#else - if (attrs.Count() > 0) { - return ((MaxLengthAttribute)attrs.First()).Value; -#endif - } else { - return DefaultMaxStringLength; - } - } - } - - public partial class SQLiteCommand - { - SQLiteConnection _conn; - private List _bindings; - - public string CommandText { get; set; } - - internal SQLiteCommand (SQLiteConnection conn) - { - _conn = conn; - _bindings = new List (); - CommandText = ""; - } - - public int ExecuteNonQuery () - { - if (_conn.Trace) { - Debug.WriteLine ("Executing: " + this); - } - - var r = SQLite3.Result.OK; - var stmt = Prepare (); - r = SQLite3.Step (stmt); - Finalize (stmt); - if (r == SQLite3.Result.Done) { - int rowsAffected = SQLite3.Changes (_conn.Handle); - return rowsAffected; - } else if (r == SQLite3.Result.Error) { - string msg = SQLite3.GetErrmsg (_conn.Handle); - throw SQLiteException.New (r, msg); - } else { - throw SQLiteException.New (r, r.ToString ()); - } - } - - public IEnumerable ExecuteDeferredQuery () - { - return ExecuteDeferredQuery(_conn.GetMapping(typeof(T))); - } - - public List ExecuteQuery () - { - return ExecuteDeferredQuery(_conn.GetMapping(typeof(T))).ToList(); - } - - public List ExecuteQuery (TableMapping map) - { - return ExecuteDeferredQuery(map).ToList(); - } - - /// - /// Invoked every time an instance is loaded from the database. - /// - /// - /// The newly created object. - /// - /// - /// This can be overridden in combination with the - /// method to hook into the life-cycle of objects. - /// - /// Type safety is not possible because MonoTouch does not support virtual generic methods. - /// - protected virtual void OnInstanceCreated (object obj) - { - // Can be overridden. - } - - public IEnumerable ExecuteDeferredQuery (TableMapping map) - { - if (_conn.Trace) { - Debug.WriteLine ("Executing Query: " + this); - } - - var stmt = Prepare (); - try - { - var cols = new TableMapping.Column[SQLite3.ColumnCount (stmt)]; - - for (int i = 0; i < cols.Length; i++) { - var name = SQLite3.ColumnName16 (stmt, i); - cols [i] = map.FindColumn (name); - } - - while (SQLite3.Step (stmt) == SQLite3.Result.Row) { - var obj = Activator.CreateInstance(map.MappedType); - for (int i = 0; i < cols.Length; i++) { - if (cols [i] == null) - continue; - var colType = SQLite3.ColumnType (stmt, i); - var val = ReadCol (stmt, i, colType, cols [i].ColumnType); - cols [i].SetValue (obj, val); - } - OnInstanceCreated (obj); - yield return (T)obj; - } - } - finally - { - SQLite3.Finalize(stmt); - } - } - - public T ExecuteScalar () - { - if (_conn.Trace) { - Debug.WriteLine ("Executing Query: " + this); - } - - T val = default(T); - - var stmt = Prepare (); - - try - { - var r = SQLite3.Step (stmt); - if (r == SQLite3.Result.Row) { - var colType = SQLite3.ColumnType (stmt, 0); - val = (T)ReadCol (stmt, 0, colType, typeof(T)); - } - else if (r == SQLite3.Result.Done) { - } - else - { - throw SQLiteException.New (r, SQLite3.GetErrmsg (_conn.Handle)); - } - } - finally - { - Finalize (stmt); - } - - return val; - } - - public void Bind (string name, object val) - { - _bindings.Add (new Binding { - Name = name, - Value = val - }); - } - - public void Bind (object val) - { - Bind (null, val); - } - - public override string ToString () - { - var parts = new string[1 + _bindings.Count]; - parts [0] = CommandText; - var i = 1; - foreach (var b in _bindings) { - parts [i] = string.Format (" {0}: {1}", i - 1, b.Value); - i++; - } - return string.Join (Environment.NewLine, parts); - } - - Sqlite3Statement Prepare() - { - var stmt = SQLite3.Prepare2 (_conn.Handle, CommandText); - BindAll (stmt); - return stmt; - } - - void Finalize (Sqlite3Statement stmt) - { - SQLite3.Finalize (stmt); - } - - void BindAll (Sqlite3Statement stmt) - { - int nextIdx = 1; - foreach (var b in _bindings) { - if (b.Name != null) { - b.Index = SQLite3.BindParameterIndex (stmt, b.Name); - } else { - b.Index = nextIdx++; - } - - BindParameter (stmt, b.Index, b.Value, _conn.StoreDateTimeAsTicks); - } - } - - internal static IntPtr NegativePointer = new IntPtr (-1); - - internal static void BindParameter (Sqlite3Statement stmt, int index, object value, bool storeDateTimeAsTicks) - { - if (value == null) { - SQLite3.BindNull (stmt, index); - } else { - if (value is Int32) { - SQLite3.BindInt (stmt, index, (int)value); - } else if (value is String) { - SQLite3.BindText (stmt, index, (string)value, -1, NegativePointer); - } else if (value is Byte || value is UInt16 || value is SByte || value is Int16) { - SQLite3.BindInt (stmt, index, Convert.ToInt32 (value)); - } else if (value is Boolean) { - SQLite3.BindInt (stmt, index, (bool)value ? 1 : 0); - } else if (value is UInt32 || value is Int64) { - SQLite3.BindInt64 (stmt, index, Convert.ToInt64 (value)); - } else if (value is Single || value is Double || value is Decimal) { - SQLite3.BindDouble (stmt, index, Convert.ToDouble (value)); - } else if (value is DateTime) { - if (storeDateTimeAsTicks) { - SQLite3.BindInt64 (stmt, index, ((DateTime)value).Ticks); - } - else { - SQLite3.BindText (stmt, index, ((DateTime)value).ToString ("yyyy-MM-dd HH:mm:ss"), -1, NegativePointer); - } -#if !NETFX_CORE - } else if (value.GetType().IsEnum) { -#else - } else if (value.GetType().GetTypeInfo().IsEnum) { -#endif - SQLite3.BindInt (stmt, index, Convert.ToInt32 (value)); - } else if (value is byte[]){ - SQLite3.BindBlob(stmt, index, (byte[]) value, ((byte[]) value).Length, NegativePointer); - } else if (value is Guid) { - SQLite3.BindText(stmt, index, ((Guid)value).ToString(), 72, NegativePointer); - } else { - throw new NotSupportedException("Cannot store type: " + value.GetType()); - } - } - } - - class Binding - { - public string Name { get; set; } - - public object Value { get; set; } - - public int Index { get; set; } - } - - object ReadCol (Sqlite3Statement stmt, int index, SQLite3.ColType type, Type clrType) - { - if (type == SQLite3.ColType.Null) { - return null; - } else { - if (clrType == typeof(String)) { - return SQLite3.ColumnString (stmt, index); - } else if (clrType == typeof(Int32)) { - return (int)SQLite3.ColumnInt (stmt, index); - } else if (clrType == typeof(Boolean)) { - return SQLite3.ColumnInt (stmt, index) == 1; - } else if (clrType == typeof(double)) { - return SQLite3.ColumnDouble (stmt, index); - } else if (clrType == typeof(float)) { - return (float)SQLite3.ColumnDouble (stmt, index); - } else if (clrType == typeof(DateTime)) { - if (_conn.StoreDateTimeAsTicks) { - return new DateTime (SQLite3.ColumnInt64 (stmt, index)); - } - else { - var text = SQLite3.ColumnString (stmt, index); - return DateTime.Parse (text); - } -#if !NETFX_CORE - } else if (clrType.IsEnum) { -#else - } else if (clrType.GetTypeInfo().IsEnum) { -#endif - return SQLite3.ColumnInt (stmt, index); - } else if (clrType == typeof(Int64)) { - return SQLite3.ColumnInt64 (stmt, index); - } else if (clrType == typeof(UInt32)) { - return (uint)SQLite3.ColumnInt64 (stmt, index); - } else if (clrType == typeof(decimal)) { - return (decimal)SQLite3.ColumnDouble (stmt, index); - } else if (clrType == typeof(Byte)) { - return (byte)SQLite3.ColumnInt (stmt, index); - } else if (clrType == typeof(UInt16)) { - return (ushort)SQLite3.ColumnInt (stmt, index); - } else if (clrType == typeof(Int16)) { - return (short)SQLite3.ColumnInt (stmt, index); - } else if (clrType == typeof(sbyte)) { - return (sbyte)SQLite3.ColumnInt (stmt, index); - } else if (clrType == typeof(byte[])) { - return SQLite3.ColumnByteArray (stmt, index); - } else if (clrType == typeof(Guid)) { - var text = SQLite3.ColumnString(stmt, index); - return new Guid(text); - } else{ - throw new NotSupportedException ("Don't know how to read " + clrType); - } - } - } - } - - /// - /// Since the insert never changed, we only need to prepare once. - /// - public class PreparedSqlLiteInsertCommand : IDisposable - { - public bool Initialized { get; set; } - - protected SQLiteConnection Connection { get; set; } - - public string CommandText { get; set; } - - protected Sqlite3Statement Statement { get; set; } - internal static readonly Sqlite3Statement NullStatement = default(Sqlite3Statement); - - internal PreparedSqlLiteInsertCommand (SQLiteConnection conn) - { - Connection = conn; - } - - public int ExecuteNonQuery (object[] source) - { - if (Connection.Trace) { - Debug.WriteLine ("Executing: " + CommandText); - } - - var r = SQLite3.Result.OK; - - if (!Initialized) { - Statement = Prepare (); - Initialized = true; - } - - //bind the values. - if (source != null) { - for (int i = 0; i < source.Length; i++) { - SQLiteCommand.BindParameter (Statement, i + 1, source [i], Connection.StoreDateTimeAsTicks); - } - } - r = SQLite3.Step (Statement); - - if (r == SQLite3.Result.Done) { - int rowsAffected = SQLite3.Changes (Connection.Handle); - SQLite3.Reset (Statement); - return rowsAffected; - } else if (r == SQLite3.Result.Error) { - string msg = SQLite3.GetErrmsg (Connection.Handle); - SQLite3.Reset (Statement); - throw SQLiteException.New (r, msg); - } else { - SQLite3.Reset (Statement); - throw SQLiteException.New (r, r.ToString ()); - } - } - - protected virtual Sqlite3Statement Prepare () - { - var stmt = SQLite3.Prepare2 (Connection.Handle, CommandText); - return stmt; - } - - public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - - private void Dispose (bool disposing) - { - if (Statement != NullStatement) { - try { - SQLite3.Finalize (Statement); - } finally { - Statement = NullStatement; - Connection = null; - } - } - } - - ~PreparedSqlLiteInsertCommand () - { - Dispose (false); - } - } - - public abstract class BaseTableQuery - { - protected class Ordering - { - public string ColumnName { get; set; } - public bool Ascending { get; set; } - } - } - - public class TableQuery : BaseTableQuery, IEnumerable - { - public SQLiteConnection Connection { get; private set; } - - public TableMapping Table { get; private set; } - - Expression _where; - List _orderBys; - int? _limit; - int? _offset; - - BaseTableQuery _joinInner; - Expression _joinInnerKeySelector; - BaseTableQuery _joinOuter; - Expression _joinOuterKeySelector; - Expression _joinSelector; - - Expression _selector; - - TableQuery (SQLiteConnection conn, TableMapping table) - { - Connection = conn; - Table = table; - } - - public TableQuery (SQLiteConnection conn) - { - Connection = conn; - Table = Connection.GetMapping (typeof(T)); - } - - public TableQuery Clone () - { - var q = new TableQuery (Connection, Table); - q._where = _where; - q._deferred = _deferred; - if (_orderBys != null) { - q._orderBys = new List (_orderBys); - } - q._limit = _limit; - q._offset = _offset; - q._joinInner = _joinInner; - q._joinInnerKeySelector = _joinInnerKeySelector; - q._joinOuter = _joinOuter; - q._joinOuterKeySelector = _joinOuterKeySelector; - q._joinSelector = _joinSelector; - q._selector = _selector; - return q; - } - - public TableQuery Where (Expression> predExpr) - { - if (predExpr.NodeType == ExpressionType.Lambda) { - var lambda = (LambdaExpression)predExpr; - var pred = lambda.Body; - var q = Clone (); - q.AddWhere (pred); - return q; - } else { - throw new NotSupportedException ("Must be a predicate"); - } - } - - public TableQuery Take (int n) - { - var q = Clone (); - q._limit = n; - return q; - } - - public TableQuery Skip (int n) - { - var q = Clone (); - q._offset = n; - return q; - } - - public T ElementAt (int index) - { - return Skip (index).Take (1).First (); - } - - bool _deferred; - public TableQuery Deferred () - { - var q = Clone (); - q._deferred = true; - return q; - } - - public TableQuery OrderBy (Expression> orderExpr) - { - return AddOrderBy (orderExpr, true); - } - - public TableQuery OrderByDescending (Expression> orderExpr) - { - return AddOrderBy (orderExpr, false); - } - - private TableQuery AddOrderBy (Expression> orderExpr, bool asc) - { - if (orderExpr.NodeType == ExpressionType.Lambda) { - var lambda = (LambdaExpression)orderExpr; - - MemberExpression mem = null; - - var unary = lambda.Body as UnaryExpression; - if (unary != null && unary.NodeType == ExpressionType.Convert) { - mem = unary.Operand as MemberExpression; - } - else { - mem = lambda.Body as MemberExpression; - } - - if (mem != null && (mem.Expression.NodeType == ExpressionType.Parameter)) { - var q = Clone (); - if (q._orderBys == null) { - q._orderBys = new List (); - } - q._orderBys.Add (new Ordering { - ColumnName = Table.FindColumnWithPropertyName(mem.Member.Name).Name, - Ascending = asc - }); - return q; - } else { - throw new NotSupportedException ("Order By does not support: " + orderExpr); - } - } else { - throw new NotSupportedException ("Must be a predicate"); - } - } - - private void AddWhere (Expression pred) - { - if (_where == null) { - _where = pred; - } else { - _where = Expression.AndAlso (_where, pred); - } - } - - public TableQuery Join ( - TableQuery inner, - Expression> outerKeySelector, - Expression> innerKeySelector, - Expression> resultSelector) - { - var q = new TableQuery (Connection, Connection.GetMapping (typeof (TResult))) { - _joinOuter = this, - _joinOuterKeySelector = outerKeySelector, - _joinInner = inner, - _joinInnerKeySelector = innerKeySelector, - _joinSelector = resultSelector, - }; - return q; - } - - public TableQuery Select (Expression> selector) - { - var q = Clone (); - q._selector = selector; - return q; - } - - private SQLiteCommand GenerateCommand (string selectionList) - { - if (_joinInner != null && _joinOuter != null) { - throw new NotSupportedException ("Joins are not supported."); - } - else { - var cmdText = "select " + selectionList + " from \"" + Table.TableName + "\""; - var args = new List (); - if (_where != null) { - var w = CompileExpr (_where, args); - cmdText += " where " + w.CommandText; - } - if ((_orderBys != null) && (_orderBys.Count > 0)) { - var t = string.Join (", ", _orderBys.Select (o => "\"" + o.ColumnName + "\"" + (o.Ascending ? "" : " desc")).ToArray ()); - cmdText += " order by " + t; - } - if (_limit.HasValue) { - cmdText += " limit " + _limit.Value; - } - if (_offset.HasValue) { - if (!_limit.HasValue) { - cmdText += " limit -1 "; - } - cmdText += " offset " + _offset.Value; - } - return Connection.CreateCommand (cmdText, args.ToArray ()); - } - } - - class CompileResult - { - public string CommandText { get; set; } - - public object Value { get; set; } - } - - private CompileResult CompileExpr (Expression expr, List queryArgs) - { - if (expr == null) { - throw new NotSupportedException ("Expression is NULL"); - } else if (expr is BinaryExpression) { - var bin = (BinaryExpression)expr; - - var leftr = CompileExpr (bin.Left, queryArgs); - var rightr = CompileExpr (bin.Right, queryArgs); - - //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null") - string text; - if (leftr.CommandText == "?" && leftr.Value == null) - text = CompileNullBinaryExpression(bin, rightr); - else if (rightr.CommandText == "?" && rightr.Value == null) - text = CompileNullBinaryExpression(bin, leftr); - else - text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")"; - return new CompileResult { CommandText = text }; - } else if (expr.NodeType == ExpressionType.Call) { - - var call = (MethodCallExpression)expr; - var args = new CompileResult[call.Arguments.Count]; - var obj = call.Object != null ? CompileExpr (call.Object, queryArgs) : null; - - for (var i = 0; i < args.Length; i++) { - args [i] = CompileExpr (call.Arguments [i], queryArgs); - } - - var sqlCall = ""; - - if (call.Method.Name == "Like" && args.Length == 2) { - sqlCall = "(" + args [0].CommandText + " like " + args [1].CommandText + ")"; - } - else if (call.Method.Name == "Contains" && args.Length == 2) { - sqlCall = "(" + args [1].CommandText + " in " + args [0].CommandText + ")"; - } - else if (call.Method.Name == "Contains" && args.Length == 1) { - if (call.Object != null && call.Object.Type == typeof(string)) { - sqlCall = "(" + obj.CommandText + " like ('%' || " + args [0].CommandText + " || '%'))"; - } - else { - sqlCall = "(" + args [0].CommandText + " in " + obj.CommandText + ")"; - } - } - else if (call.Method.Name == "StartsWith" && args.Length == 1) { - sqlCall = "(" + obj.CommandText + " like (" + args [0].CommandText + " || '%'))"; - } - else if (call.Method.Name == "EndsWith" && args.Length == 1) { - sqlCall = "(" + obj.CommandText + " like ('%' || " + args [0].CommandText + "))"; - } - else if (call.Method.Name == "Equals" && args.Length == 1) { - sqlCall = "(" + obj.CommandText + " = (" + args[0].CommandText + "))"; - } else if (call.Method.Name == "ToLower") { - sqlCall = "(lower(" + obj.CommandText + "))"; - } else { - sqlCall = call.Method.Name.ToLower () + "(" + string.Join (",", args.Select (a => a.CommandText).ToArray ()) + ")"; - } - return new CompileResult { CommandText = sqlCall }; - - } else if (expr.NodeType == ExpressionType.Constant) { - var c = (ConstantExpression)expr; - queryArgs.Add (c.Value); - return new CompileResult { - CommandText = "?", - Value = c.Value - }; - } else if (expr.NodeType == ExpressionType.Convert) { - var u = (UnaryExpression)expr; - var ty = u.Type; - var valr = CompileExpr (u.Operand, queryArgs); - return new CompileResult { - CommandText = valr.CommandText, - Value = valr.Value != null ? ConvertTo (valr.Value, ty) : null - }; - } else if (expr.NodeType == ExpressionType.MemberAccess) { - var mem = (MemberExpression)expr; - - if (mem.Expression!=null && mem.Expression.NodeType == ExpressionType.Parameter) { - // - // This is a column of our table, output just the column name - // Need to translate it if that column name is mapped - // - var columnName = Table.FindColumnWithPropertyName (mem.Member.Name).Name; - return new CompileResult { CommandText = "\"" + columnName + "\"" }; - } else { - object obj = null; - if (mem.Expression != null) { - var r = CompileExpr (mem.Expression, queryArgs); - if (r.Value == null) { - throw new NotSupportedException ("Member access failed to compile expression"); - } - if (r.CommandText == "?") { - queryArgs.RemoveAt (queryArgs.Count - 1); - } - obj = r.Value; - } - - // - // Get the member value - // - object val = null; - -#if !NETFX_CORE - if (mem.Member.MemberType == MemberTypes.Property) { -#else - if (mem.Member is PropertyInfo) { -#endif - var m = (PropertyInfo)mem.Member; - val = m.GetValue (obj, null); -#if !NETFX_CORE - } else if (mem.Member.MemberType == MemberTypes.Field) { -#else - } else if (mem.Member is FieldInfo) { -#endif -#if SILVERLIGHT - val = Expression.Lambda (expr).Compile ().DynamicInvoke (); -#else - var m = (FieldInfo)mem.Member; - val = m.GetValue (obj); -#endif - } else { -#if !NETFX_CORE - throw new NotSupportedException ("MemberExpr: " + mem.Member.MemberType); -#else - throw new NotSupportedException ("MemberExpr: " + mem.Member.DeclaringType); -#endif - } - - // - // Work special magic for enumerables - // - if (val != null && val is System.Collections.IEnumerable && !(val is string)) { - var sb = new System.Text.StringBuilder(); - sb.Append("("); - var head = ""; - foreach (var a in (System.Collections.IEnumerable)val) { - queryArgs.Add(a); - sb.Append(head); - sb.Append("?"); - head = ","; - } - sb.Append(")"); - return new CompileResult { - CommandText = sb.ToString(), - Value = val - }; - } - else { - queryArgs.Add (val); - return new CompileResult { - CommandText = "?", - Value = val - }; - } - } - } - throw new NotSupportedException ("Cannot compile: " + expr.NodeType.ToString ()); - } - - static object ConvertTo (object obj, Type t) - { - Type nut = Nullable.GetUnderlyingType(t); - - if (nut != null) { - if (obj == null) return null; - return Convert.ChangeType (obj, nut); - } else { - return Convert.ChangeType (obj, t); - } - } - - /// - /// Compiles a BinaryExpression where one of the parameters is null. - /// - /// The non-null parameter - private string CompileNullBinaryExpression(BinaryExpression expression, CompileResult parameter) - { - if (expression.NodeType == ExpressionType.Equal) - return "(" + parameter.CommandText + " is ?)"; - else if (expression.NodeType == ExpressionType.NotEqual) - return "(" + parameter.CommandText + " is not ?)"; - else - throw new NotSupportedException("Cannot compile Null-BinaryExpression with type " + expression.NodeType.ToString()); - } - - string GetSqlName (Expression expr) - { - var n = expr.NodeType; - if (n == ExpressionType.GreaterThan) - return ">"; else if (n == ExpressionType.GreaterThanOrEqual) { - return ">="; - } else if (n == ExpressionType.LessThan) { - return "<"; - } else if (n == ExpressionType.LessThanOrEqual) { - return "<="; - } else if (n == ExpressionType.And) { - return "&"; - } else if (n == ExpressionType.AndAlso) { - return "and"; - } else if (n == ExpressionType.Or) { - return "|"; - } else if (n == ExpressionType.OrElse) { - return "or"; - } else if (n == ExpressionType.Equal) { - return "="; - } else if (n == ExpressionType.NotEqual) { - return "!="; - } else { - throw new NotSupportedException ("Cannot get SQL for: " + n); - } - } - - public int Count () - { - return GenerateCommand("count(*)").ExecuteScalar (); - } - - public int Count (Expression> predExpr) - { - return Where (predExpr).Count (); - } - - public IEnumerator GetEnumerator () - { - if (!_deferred) - return GenerateCommand("*").ExecuteQuery().GetEnumerator(); - - return GenerateCommand("*").ExecuteDeferredQuery().GetEnumerator(); - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () - { - return GetEnumerator (); - } - - public T First () - { - var query = Take (1); - return query.ToList().First (); - } - - public T FirstOrDefault () - { - var query = Take (1); - return query.ToList().FirstOrDefault (); - } - } - - public static class SQLite3 - { - public enum Result : int - { - OK = 0, - Error = 1, - Internal = 2, - Perm = 3, - Abort = 4, - Busy = 5, - Locked = 6, - NoMem = 7, - ReadOnly = 8, - Interrupt = 9, - IOError = 10, - Corrupt = 11, - NotFound = 12, - Full = 13, - CannotOpen = 14, - LockErr = 15, - Empty = 16, - SchemaChngd = 17, - TooBig = 18, - Constraint = 19, - Mismatch = 20, - Misuse = 21, - NotImplementedLFS = 22, - AccessDenied = 23, - Format = 24, - Range = 25, - NonDBFile = 26, - Row = 100, - Done = 101 - } - - public enum ConfigOption : int - { - SingleThread = 1, - MultiThread = 2, - Serialized = 3 - } - -#if !USE_CSHARP_SQLITE && !USE_WP8_NATIVE_SQLITE - [DllImport("sqlite3", EntryPoint = "sqlite3_open", CallingConvention=CallingConvention.Cdecl)] - public static extern Result Open ([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db); - - [DllImport("sqlite3", EntryPoint = "sqlite3_open_v2", CallingConvention=CallingConvention.Cdecl)] - public static extern Result Open ([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db, int flags, IntPtr zvfs); - - [DllImport("sqlite3", EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)] - public static extern Result Open(byte[] filename, out IntPtr db, int flags, IntPtr zvfs); - - [DllImport("sqlite3", EntryPoint = "sqlite3_open16", CallingConvention = CallingConvention.Cdecl)] - public static extern Result Open16([MarshalAs(UnmanagedType.LPWStr)] string filename, out IntPtr db); - - [DllImport("sqlite3", EntryPoint = "sqlite3_enable_load_extension", CallingConvention=CallingConvention.Cdecl)] - public static extern Result EnableLoadExtension (IntPtr db, int onoff); - - [DllImport("sqlite3", EntryPoint = "sqlite3_close", CallingConvention=CallingConvention.Cdecl)] - public static extern Result Close (IntPtr db); - - [DllImport("sqlite3", EntryPoint = "sqlite3_config", CallingConvention=CallingConvention.Cdecl)] - public static extern Result Config (ConfigOption option); - - [DllImport("sqlite3", EntryPoint = "sqlite3_win32_set_directory", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Unicode)] - public static extern int SetDirectory (uint directoryType, string directoryPath); - - [DllImport("sqlite3", EntryPoint = "sqlite3_busy_timeout", CallingConvention=CallingConvention.Cdecl)] - public static extern Result BusyTimeout (IntPtr db, int milliseconds); - - [DllImport("sqlite3", EntryPoint = "sqlite3_changes", CallingConvention=CallingConvention.Cdecl)] - public static extern int Changes (IntPtr db); - - [DllImport("sqlite3", EntryPoint = "sqlite3_prepare_v2", CallingConvention=CallingConvention.Cdecl)] - public static extern Result Prepare2 (IntPtr db, [MarshalAs(UnmanagedType.LPStr)] string sql, int numBytes, out IntPtr stmt, IntPtr pzTail); - - public static IntPtr Prepare2 (IntPtr db, string query) - { - IntPtr stmt; - var r = Prepare2 (db, query, query.Length, out stmt, IntPtr.Zero); - if (r != Result.OK) { - throw SQLiteException.New (r, GetErrmsg (db)); - } - return stmt; - } - - [DllImport("sqlite3", EntryPoint = "sqlite3_step", CallingConvention=CallingConvention.Cdecl)] - public static extern Result Step (IntPtr stmt); - - [DllImport("sqlite3", EntryPoint = "sqlite3_reset", CallingConvention=CallingConvention.Cdecl)] - public static extern Result Reset (IntPtr stmt); - - [DllImport("sqlite3", EntryPoint = "sqlite3_finalize", CallingConvention=CallingConvention.Cdecl)] - public static extern Result Finalize (IntPtr stmt); - - [DllImport("sqlite3", EntryPoint = "sqlite3_last_insert_rowid", CallingConvention=CallingConvention.Cdecl)] - public static extern long LastInsertRowid (IntPtr db); - - [DllImport("sqlite3", EntryPoint = "sqlite3_errmsg16", CallingConvention=CallingConvention.Cdecl)] - public static extern IntPtr Errmsg (IntPtr db); - - public static string GetErrmsg (IntPtr db) - { - return Marshal.PtrToStringUni (Errmsg (db)); - } - - [DllImport("sqlite3", EntryPoint = "sqlite3_bind_parameter_index", CallingConvention=CallingConvention.Cdecl)] - public static extern int BindParameterIndex (IntPtr stmt, [MarshalAs(UnmanagedType.LPStr)] string name); - - [DllImport("sqlite3", EntryPoint = "sqlite3_bind_null", CallingConvention=CallingConvention.Cdecl)] - public static extern int BindNull (IntPtr stmt, int index); - - [DllImport("sqlite3", EntryPoint = "sqlite3_bind_int", CallingConvention=CallingConvention.Cdecl)] - public static extern int BindInt (IntPtr stmt, int index, int val); - - [DllImport("sqlite3", EntryPoint = "sqlite3_bind_int64", CallingConvention=CallingConvention.Cdecl)] - public static extern int BindInt64 (IntPtr stmt, int index, long val); - - [DllImport("sqlite3", EntryPoint = "sqlite3_bind_double", CallingConvention=CallingConvention.Cdecl)] - public static extern int BindDouble (IntPtr stmt, int index, double val); - - [DllImport("sqlite3", EntryPoint = "sqlite3_bind_text16", CallingConvention=CallingConvention.Cdecl, CharSet = CharSet.Unicode)] - public static extern int BindText (IntPtr stmt, int index, [MarshalAs(UnmanagedType.LPWStr)] string val, int n, IntPtr free); - - [DllImport("sqlite3", EntryPoint = "sqlite3_bind_blob", CallingConvention=CallingConvention.Cdecl)] - public static extern int BindBlob (IntPtr stmt, int index, byte[] val, int n, IntPtr free); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_count", CallingConvention=CallingConvention.Cdecl)] - public static extern int ColumnCount (IntPtr stmt); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_name", CallingConvention=CallingConvention.Cdecl)] - public static extern IntPtr ColumnName (IntPtr stmt, int index); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_name16", CallingConvention=CallingConvention.Cdecl)] - static extern IntPtr ColumnName16Internal (IntPtr stmt, int index); - public static string ColumnName16(IntPtr stmt, int index) - { - return Marshal.PtrToStringUni(ColumnName16Internal(stmt, index)); - } - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_type", CallingConvention=CallingConvention.Cdecl)] - public static extern ColType ColumnType (IntPtr stmt, int index); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_int", CallingConvention=CallingConvention.Cdecl)] - public static extern int ColumnInt (IntPtr stmt, int index); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_int64", CallingConvention=CallingConvention.Cdecl)] - public static extern long ColumnInt64 (IntPtr stmt, int index); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_double", CallingConvention=CallingConvention.Cdecl)] - public static extern double ColumnDouble (IntPtr stmt, int index); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_text", CallingConvention=CallingConvention.Cdecl)] - public static extern IntPtr ColumnText (IntPtr stmt, int index); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_text16", CallingConvention=CallingConvention.Cdecl)] - public static extern IntPtr ColumnText16 (IntPtr stmt, int index); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_blob", CallingConvention=CallingConvention.Cdecl)] - public static extern IntPtr ColumnBlob (IntPtr stmt, int index); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_bytes", CallingConvention=CallingConvention.Cdecl)] - public static extern int ColumnBytes (IntPtr stmt, int index); - - public static string ColumnString (IntPtr stmt, int index) - { - return Marshal.PtrToStringUni (SQLite3.ColumnText16 (stmt, index)); - } - - public static byte[] ColumnByteArray (IntPtr stmt, int index) - { - int length = ColumnBytes (stmt, index); - var result = new byte[length]; - if (length > 0) - Marshal.Copy (ColumnBlob (stmt, index), result, 0, length); - return result; - } -#else - public static Result Open(string filename, out Sqlite3DatabaseHandle db) - { - return (Result) Sqlite3.sqlite3_open(filename, out db); - } - - public static Result Open(string filename, out Sqlite3DatabaseHandle db, int flags, IntPtr zVfs) - { -#if USE_WP8_NATIVE_SQLITE - return (Result)Sqlite3.sqlite3_open_v2(filename, out db, flags, ""); -#else - return (Result)Sqlite3.sqlite3_open_v2(filename, out db, flags, null); -#endif - } - - public static Result Close(Sqlite3DatabaseHandle db) - { - return (Result)Sqlite3.sqlite3_close(db); - } - - public static Result BusyTimeout(Sqlite3DatabaseHandle db, int milliseconds) - { - return (Result)Sqlite3.sqlite3_busy_timeout(db, milliseconds); - } - - public static int Changes(Sqlite3DatabaseHandle db) - { - return Sqlite3.sqlite3_changes(db); - } - - public static Sqlite3Statement Prepare2(Sqlite3DatabaseHandle db, string query) - { - Sqlite3Statement stmt = default(Sqlite3Statement); -#if USE_WP8_NATIVE_SQLITE - var r = Sqlite3.sqlite3_prepare_v2(db, query, out stmt); -#else - stmt = new Sqlite3Statement(); - var r = Sqlite3.sqlite3_prepare_v2(db, query, -1, ref stmt, 0); -#endif - if (r != 0) - { - throw SQLiteException.New((Result)r, GetErrmsg(db)); - } - return stmt; - } - - public static Result Step(Sqlite3Statement stmt) - { - return (Result)Sqlite3.sqlite3_step(stmt); - } - - public static Result Reset(Sqlite3Statement stmt) - { - return (Result)Sqlite3.sqlite3_reset(stmt); - } - - public static Result Finalize(Sqlite3Statement stmt) - { - return (Result)Sqlite3.sqlite3_finalize(stmt); - } - - public static long LastInsertRowid(Sqlite3DatabaseHandle db) - { - return Sqlite3.sqlite3_last_insert_rowid(db); - } - - public static string GetErrmsg(Sqlite3DatabaseHandle db) - { - return Sqlite3.sqlite3_errmsg(db); - } - - public static int BindParameterIndex(Sqlite3Statement stmt, string name) - { - return Sqlite3.sqlite3_bind_parameter_index(stmt, name); - } - - public static int BindNull(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_bind_null(stmt, index); - } - - public static int BindInt(Sqlite3Statement stmt, int index, int val) - { - return Sqlite3.sqlite3_bind_int(stmt, index, val); - } - - public static int BindInt64(Sqlite3Statement stmt, int index, long val) - { - return Sqlite3.sqlite3_bind_int64(stmt, index, val); - } - - public static int BindDouble(Sqlite3Statement stmt, int index, double val) - { - return Sqlite3.sqlite3_bind_double(stmt, index, val); - } - - public static int BindText(Sqlite3Statement stmt, int index, string val, int n, IntPtr free) - { -#if USE_WP8_NATIVE_SQLITE - return Sqlite3.sqlite3_bind_text(stmt, index, val, n); -#else - return Sqlite3.sqlite3_bind_text(stmt, index, val, n, null); -#endif - } - - public static int BindBlob(Sqlite3Statement stmt, int index, byte[] val, int n, IntPtr free) - { -#if USE_WP8_NATIVE_SQLITE - return Sqlite3.sqlite3_bind_blob(stmt, index, val, n); -#else - return Sqlite3.sqlite3_bind_blob(stmt, index, val, n, null); -#endif - } - - public static int ColumnCount(Sqlite3Statement stmt) - { - return Sqlite3.sqlite3_column_count(stmt); - } - - public static string ColumnName(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_column_name(stmt, index); - } - - public static string ColumnName16(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_column_name(stmt, index); - } - - public static ColType ColumnType(Sqlite3Statement stmt, int index) - { - return (ColType)Sqlite3.sqlite3_column_type(stmt, index); - } - - public static int ColumnInt(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_column_int(stmt, index); - } - - public static long ColumnInt64(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_column_int64(stmt, index); - } - - public static double ColumnDouble(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_column_double(stmt, index); - } - - public static string ColumnText(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_column_text(stmt, index); - } - - public static string ColumnText16(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_column_text(stmt, index); - } - - public static byte[] ColumnBlob(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_column_blob(stmt, index); - } - - public static int ColumnBytes(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_column_bytes(stmt, index); - } - - public static string ColumnString(Sqlite3Statement stmt, int index) - { - return Sqlite3.sqlite3_column_text(stmt, index); - } - - public static byte[] ColumnByteArray(Sqlite3Statement stmt, int index) - { - return ColumnBlob(stmt, index); - } -#endif - - public enum ColType : int - { - Integer = 1, - Float = 2, - Text = 3, - Blob = 4, - Null = 5 - } - } -} diff --git a/src/SQLiteAsync.cs b/src/SQLiteAsync.cs deleted file mode 100644 index b4cf34e07..000000000 --- a/src/SQLiteAsync.cs +++ /dev/null @@ -1,486 +0,0 @@ -// -// Copyright (c) 2012 Krueger Systems, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Threading; -using System.Threading.Tasks; - -namespace SQLite -{ - public partial class SQLiteAsyncConnection - { - SQLiteConnectionString _connectionString; - - public SQLiteAsyncConnection (string databasePath, bool storeDateTimeAsTicks = false) - { - _connectionString = new SQLiteConnectionString (databasePath, storeDateTimeAsTicks); - } - - SQLiteConnectionWithLock GetConnection () - { - return SQLiteConnectionPool.Shared.GetConnection (_connectionString); - } - - public Task CreateTableAsync () - where T : new () - { - return CreateTablesAsync (typeof (T)); - } - - public Task CreateTablesAsync () - where T : new () - where T2 : new () - { - return CreateTablesAsync (typeof (T), typeof (T2)); - } - - public Task CreateTablesAsync () - where T : new () - where T2 : new () - where T3 : new () - { - return CreateTablesAsync (typeof (T), typeof (T2), typeof (T3)); - } - - public Task CreateTablesAsync () - where T : new () - where T2 : new () - where T3 : new () - where T4 : new () - { - return CreateTablesAsync (typeof (T), typeof (T2), typeof (T3), typeof (T4)); - } - - public Task CreateTablesAsync () - where T : new () - where T2 : new () - where T3 : new () - where T4 : new () - where T5 : new () - { - return CreateTablesAsync (typeof (T), typeof (T2), typeof (T3), typeof (T4), typeof (T5)); - } - - public Task CreateTablesAsync (params Type[] types) - { - return Task.Factory.StartNew (() => { - CreateTablesResult result = new CreateTablesResult (); - var conn = GetConnection (); - using (conn.Lock ()) { - foreach (Type type in types) { - int aResult = conn.CreateTable (type); - result.Results[type] = aResult; - } - } - return result; - }); - } - - public Task DropTableAsync () - where T : new () - { - return Task.Factory.StartNew (() => { - var conn = GetConnection (); - using (conn.Lock ()) { - return conn.DropTable (); - } - }); - } - - public Task InsertAsync (object item) - { - return Task.Factory.StartNew (() => { - var conn = GetConnection (); - using (conn.Lock ()) { - return conn.Insert (item); - } - }); - } - - public Task UpdateAsync (object item) - { - return Task.Factory.StartNew (() => { - var conn = GetConnection (); - using (conn.Lock ()) { - return conn.Update (item); - } - }); - } - - public Task DeleteAsync (object item) - { - return Task.Factory.StartNew (() => { - var conn = GetConnection (); - using (conn.Lock ()) { - return conn.Delete (item); - } - }); - } - - public Task GetAsync(object pk) - where T : new() - { - return Task.Factory.StartNew(() => - { - var conn = GetConnection(); - using (conn.Lock()) - { - return conn.Get(pk); - } - }); - } - - public Task FindAsync (object pk) - where T : new () - { - return Task.Factory.StartNew (() => { - var conn = GetConnection (); - using (conn.Lock ()) { - return conn.Find (pk); - } - }); - } - - public Task GetAsync (Expression> predicate) - where T : new() - { - return Task.Factory.StartNew(() => - { - var conn = GetConnection(); - using (conn.Lock()) - { - return conn.Get (predicate); - } - }); - } - - public Task FindAsync (Expression> predicate) - where T : new () - { - return Task.Factory.StartNew (() => { - var conn = GetConnection (); - using (conn.Lock ()) { - return conn.Find (predicate); - } - }); - } - - public Task ExecuteAsync (string query, params object[] args) - { - return Task.Factory.StartNew (() => { - var conn = GetConnection (); - using (conn.Lock ()) { - return conn.Execute (query, args); - } - }); - } - - public Task InsertAllAsync (IEnumerable items) - { - return Task.Factory.StartNew (() => { - var conn = GetConnection (); - using (conn.Lock ()) { - return conn.InsertAll (items); - } - }); - } - - [Obsolete("Will cause a deadlock if any call in action ends up in a different thread. Use RunInTransactionAsync(Action) instead.")] - public Task RunInTransactionAsync (Action action) - { - return Task.Factory.StartNew (() => { - var conn = this.GetConnection (); - using (conn.Lock ()) { - conn.BeginTransaction (); - try { - action (this); - conn.Commit (); - } - catch (Exception) { - conn.Rollback (); - throw; - } - } - }); - } - - public Task RunInTransactionAsync(Action action) - { - return Task.Factory.StartNew(() => - { - var conn = this.GetConnection(); - using (conn.Lock()) - { - conn.BeginTransaction(); - try - { - action(conn); - conn.Commit(); - } - catch (Exception) - { - conn.Rollback(); - throw; - } - } - }); - } - - public AsyncTableQuery Table () - where T : new () - { - // - // This isn't async as the underlying connection doesn't go out to the database - // until the query is performed. The Async methods are on the query iteself. - // - var conn = GetConnection (); - return new AsyncTableQuery (conn.Table ()); - } - - public Task ExecuteScalarAsync (string sql, params object[] args) - { - return Task.Factory.StartNew (() => { - var conn = GetConnection (); - using (conn.Lock ()) { - var command = conn.CreateCommand (sql, args); - return command.ExecuteScalar (); - } - }); - } - - public Task> QueryAsync (string sql, params object[] args) - where T : new () - { - return Task>.Factory.StartNew (() => { - var conn = GetConnection (); - using (conn.Lock ()) { - return conn.Query (sql, args); - } - }); - } - } - - // - // TODO: Bind to AsyncConnection.GetConnection instead so that delayed - // execution can still work after a Pool.Reset. - // - public class AsyncTableQuery - where T : new () - { - TableQuery _innerQuery; - - public AsyncTableQuery (TableQuery innerQuery) - { - _innerQuery = innerQuery; - } - - public AsyncTableQuery Where (Expression> predExpr) - { - return new AsyncTableQuery (_innerQuery.Where (predExpr)); - } - - public AsyncTableQuery Skip (int n) - { - return new AsyncTableQuery (_innerQuery.Skip (n)); - } - - public AsyncTableQuery Take (int n) - { - return new AsyncTableQuery (_innerQuery.Take (n)); - } - - public AsyncTableQuery OrderBy (Expression> orderExpr) - { - return new AsyncTableQuery (_innerQuery.OrderBy (orderExpr)); - } - - public AsyncTableQuery OrderByDescending (Expression> orderExpr) - { - return new AsyncTableQuery (_innerQuery.OrderByDescending (orderExpr)); - } - - public Task> ToListAsync () - { - return Task.Factory.StartNew (() => { - using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { - return _innerQuery.ToList (); - } - }); - } - - public Task CountAsync () - { - return Task.Factory.StartNew (() => { - using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { - return _innerQuery.Count (); - } - }); - } - - public Task ElementAtAsync (int index) - { - return Task.Factory.StartNew (() => { - using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { - return _innerQuery.ElementAt (index); - } - }); - } - - public Task FirstAsync () - { - return Task.Factory.StartNew(() => { - using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { - return _innerQuery.First (); - } - }); - } - - public Task FirstOrDefaultAsync () - { - return Task.Factory.StartNew(() => { - using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { - return _innerQuery.FirstOrDefault (); - } - }); - } - } - - public class CreateTablesResult - { - public Dictionary Results { get; private set; } - - internal CreateTablesResult () - { - this.Results = new Dictionary (); - } - } - - class SQLiteConnectionPool - { - class Entry - { - public SQLiteConnectionString ConnectionString { get; private set; } - public SQLiteConnectionWithLock Connection { get; private set; } - - public Entry (SQLiteConnectionString connectionString) - { - ConnectionString = connectionString; - Connection = new SQLiteConnectionWithLock (connectionString); - } - - public void OnApplicationSuspended () - { - Connection.Dispose (); - Connection = null; - } - } - - readonly Dictionary _entries = new Dictionary (); - readonly object _entriesLock = new object (); - - static readonly SQLiteConnectionPool _shared = new SQLiteConnectionPool (); - - /// - /// Gets the singleton instance of the connection tool. - /// - public static SQLiteConnectionPool Shared - { - get - { - return _shared; - } - } - - public SQLiteConnectionWithLock GetConnection (SQLiteConnectionString connectionString) - { - lock (_entriesLock) { - Entry entry; - string key = connectionString.ConnectionString; - - if (!_entries.TryGetValue (key, out entry)) { - entry = new Entry (connectionString); - _entries[key] = entry; - } - - return entry.Connection; - } - } - - /// - /// Closes all connections managed by this pool. - /// - public void Reset () - { - lock (_entriesLock) { - foreach (var entry in _entries.Values) { - entry.OnApplicationSuspended (); - } - _entries.Clear (); - } - } - - /// - /// Call this method when the application is suspended. - /// - /// Behaviour here is to close any open connections. - public void ApplicationSuspended () - { - Reset (); - } - } - - class SQLiteConnectionWithLock : SQLiteConnection - { - readonly object _lockPoint = new object (); - - public SQLiteConnectionWithLock (SQLiteConnectionString connectionString) - : base (connectionString.DatabasePath, connectionString.StoreDateTimeAsTicks) - { - } - - public IDisposable Lock () - { - return new LockWrapper (_lockPoint); - } - - private class LockWrapper : IDisposable - { - object _lockPoint; - - public LockWrapper (object lockPoint) - { - _lockPoint = lockPoint; - Monitor.Enter (_lockPoint); - } - - public void Dispose () - { - Monitor.Exit (_lockPoint); - } - } - } -} - diff --git a/tests/AsyncTests.cs b/tests/AsyncTests.cs index 38060a8be..ca617f8b3 100644 --- a/tests/AsyncTests.cs +++ b/tests/AsyncTests.cs @@ -1,810 +1,969 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.IO; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; -using System.IO; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; +using SQLite.Net.Async; +using SQLite.Net.Attributes; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -namespace SQLite.Tests +namespace SQLite.Net.Tests { - // @mbrit - 2012-05-14 - NOTE - the lack of async use in this class is because the VS11 test runner falsely - // reports any failing test as succeeding if marked as async. Should be fixed in the "June 2012" drop... - - public class Customer - { - [AutoIncrement, PrimaryKey] - public int Id { get; set; } - - [MaxLength (64)] - public string FirstName { get; set; } - - [MaxLength (64)] - public string LastName { get; set; } - - [MaxLength (64)] - public string Email { get; set; } - } - - /// - /// Defines tests that exercise async behaviour. - /// - [TestFixture] - public class AsyncTests - { - private const string DatabaseName = "async.db"; - - [Test] - public void StressAsync () - { - string path = null; - var globalConn = GetConnection (ref path); - - globalConn.CreateTableAsync ().Wait (); - - var threadCount = 0; - var doneEvent = new AutoResetEvent (false); - var n = 500; - var errors = new List (); - for (var i = 0; i < n; i++) { - Task.Factory.StartNew (delegate { - try { - var conn = GetConnection (); - var obj = new Customer { - FirstName = i.ToString (), - }; - conn.InsertAsync (obj).Wait (); - if (obj.Id == 0) { - lock (errors) { - errors.Add ("Bad Id"); - } - } - var obj2 = (from c in conn.Table () where c.Id == obj.Id select c).ToListAsync ().Result.FirstOrDefault(); - if (obj2 == null) { - lock (errors) { - errors.Add ("Failed query"); - } - } - } - catch (Exception ex) { - lock (errors) { - errors.Add (ex.Message); - } - } - threadCount++; - if (threadCount == n) { - doneEvent.Set(); - } - }); - } - doneEvent.WaitOne (); - - var count = globalConn.Table ().CountAsync ().Result; - - Assert.AreEqual (0, errors.Count); - Assert.AreEqual (n, count); - } - - [Test] - public void TestCreateTableAsync () - { - string path = null; - var conn = GetConnection (ref path); - - // drop the customer table... - conn.ExecuteAsync ("drop table if exists Customer").Wait (); - - // run... - conn.CreateTableAsync ().Wait (); - - // check... - using (SQLiteConnection check = new SQLiteConnection (path)) { - // run it - if it's missing we'll get a failure... - check.Execute ("select * from Customer"); - } - } - - SQLiteAsyncConnection GetConnection () - { - string path = null; - return GetConnection (ref path); - } - - string _path; - string _connectionString; - - [SetUp] - public void SetUp() - { - SQLite.SQLiteConnectionPool.Shared.Reset (); -#if NETFX_CORE - _connectionString = DatabaseName; - _path = Path.Combine (Windows.Storage.ApplicationData.Current.LocalFolder.Path, DatabaseName); - try { - var f = Windows.Storage.StorageFile.GetFileFromPathAsync (_path).AsTask ().Result; - f.DeleteAsync ().AsTask ().Wait (); - } - catch (Exception) { - } -#else - _connectionString = Path.Combine (Path.GetTempPath (), DatabaseName); - _path = _connectionString; - System.IO.File.Delete (_path); -#endif - } - - SQLiteAsyncConnection GetConnection (ref string path) - { - path = _path; - return new SQLiteAsyncConnection (_connectionString); - } - - [Test] - public void TestDropTableAsync () - { - string path = null; - var conn = GetConnection (ref path); - conn.CreateTableAsync ().Wait (); - - // drop it... - conn.DropTableAsync ().Wait (); - - // check... - using (SQLiteConnection check = new SQLiteConnection (path)) { - // load it back and check - should be missing - var command = check.CreateCommand ("select name from sqlite_master where type='table' and name='customer'"); - Assert.IsNull (command.ExecuteScalar ()); - } - } - - private Customer CreateCustomer () - { - Customer customer = new Customer () { - FirstName = "foo", - LastName = "bar", - Email = Guid.NewGuid ().ToString () - }; - return customer; - } - - [Test] - public void TestInsertAsync () - { - // create... - Customer customer = this.CreateCustomer (); - - // connect... - string path = null; - var conn = GetConnection (ref path); - conn.CreateTableAsync ().Wait (); - - // run... - conn.InsertAsync (customer).Wait (); - - // check that we got an id... - Assert.AreNotEqual (0, customer.Id); - - // check... - using (SQLiteConnection check = new SQLiteConnection (path)) { - // load it back... - Customer loaded = check.Get (customer.Id); - Assert.AreEqual (loaded.Id, customer.Id); - } - } - - [Test] - public void TestUpdateAsync () - { - // create... - Customer customer = CreateCustomer (); - - // connect... - string path = null; - var conn = GetConnection (ref path); - conn.CreateTableAsync ().Wait (); - - // run... - conn.InsertAsync (customer).Wait (); - - // change it... - string newEmail = Guid.NewGuid ().ToString (); - customer.Email = newEmail; - - // save it... - conn.UpdateAsync (customer).Wait (); - - // check... - using (SQLiteConnection check = new SQLiteConnection (path)) { - // load it back - should be changed... - Customer loaded = check.Get (customer.Id); - Assert.AreEqual (newEmail, loaded.Email); - } - } - - [Test] - public void TestDeleteAsync () - { - // create... - Customer customer = CreateCustomer (); - - // connect... - string path = null; - var conn = GetConnection (ref path); - conn.CreateTableAsync ().Wait (); - - // run... - conn.InsertAsync (customer).Wait (); - - // delete it... - conn.DeleteAsync (customer).Wait (); - - // check... - using (SQLiteConnection check = new SQLiteConnection (path)) { - // load it back - should be null... - var loaded = check.Table ().Where (v => v.Id == customer.Id).ToList (); - Assert.AreEqual (0, loaded.Count); - } - } - - [Test] - public void GetAsync () - { - // create... - Customer customer = new Customer (); - customer.FirstName = "foo"; - customer.LastName = "bar"; - customer.Email = Guid.NewGuid ().ToString (); - - // connect and insert... - string path = null; - var conn = GetConnection (ref path); - conn.CreateTableAsync ().Wait (); - conn.InsertAsync (customer).Wait (); - - // check... - Assert.AreNotEqual (0, customer.Id); - - // get it back... - var task = conn.GetAsync (customer.Id); - task.Wait (); - Customer loaded = task.Result; - - // check... - Assert.AreEqual (customer.Id, loaded.Id); - } - - [Test] - public void FindAsyncWithExpression () - { - // create... - Customer customer = new Customer (); - customer.FirstName = "foo"; - customer.LastName = "bar"; - customer.Email = Guid.NewGuid ().ToString (); - - // connect and insert... - string path = null; - var conn = GetConnection (ref path); - conn.CreateTableAsync ().Wait (); - conn.InsertAsync (customer).Wait (); - - // check... - Assert.AreNotEqual (0, customer.Id); - - // get it back... - var task = conn.FindAsync (x => x.Id == customer.Id); - task.Wait (); - Customer loaded = task.Result; - - // check... - Assert.AreEqual (customer.Id, loaded.Id); - } - - [Test] - public void FindAsyncWithExpressionNull () - { - // connect and insert... - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - - // get it back... - var task = conn.FindAsync (x => x.Id == 1); - task.Wait (); - var loaded = task.Result; - - // check... - Assert.IsNull (loaded); - } - - [Test] - public void TestFindAsyncItemPresent () - { - // create... - Customer customer = CreateCustomer (); - - // connect and insert... - string path = null; - var conn = GetConnection (ref path); - conn.CreateTableAsync ().Wait (); - conn.InsertAsync (customer).Wait (); - - // check... - Assert.AreNotEqual (0, customer.Id); - - // get it back... - var task = conn.FindAsync (customer.Id); - task.Wait (); - Customer loaded = task.Result; - - // check... - Assert.AreEqual (customer.Id, loaded.Id); - } - - [Test] - public void TestFindAsyncItemMissing () - { - // connect and insert... - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - - // now get one that doesn't exist... - var task = conn.FindAsync (-1); - task.Wait (); - - // check... - Assert.IsNull (task.Result); - } - - [Test] - public void TestQueryAsync () - { - // connect... - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - - // insert some... - List customers = new List (); - for (int index = 0; index < 5; index++) { - Customer customer = CreateCustomer (); - - // insert... - conn.InsertAsync (customer).Wait (); - - // add... - customers.Add (customer); - } - - // return the third one... - var task = conn.QueryAsync ("select * from customer where id=?", customers[2].Id); - task.Wait (); - var loaded = task.Result; - - // check... - Assert.AreEqual (1, loaded.Count); - Assert.AreEqual (customers[2].Email, loaded[0].Email); - } - - [Test] - public void TestTableAsync () - { - // connect... - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - conn.ExecuteAsync ("delete from customer").Wait (); - - // insert some... - List customers = new List (); - for (int index = 0; index < 5; index++) { - Customer customer = new Customer (); - customer.FirstName = "foo"; - customer.LastName = "bar"; - customer.Email = Guid.NewGuid ().ToString (); - - // insert... - conn.InsertAsync (customer).Wait (); - - // add... - customers.Add (customer); - } - - // run the table operation... - var query = conn.Table (); - var loaded = query.ToListAsync ().Result; - - // check that we got them all back... - Assert.AreEqual (5, loaded.Count); - Assert.IsNotNull (loaded.Where (v => v.Id == customers[0].Id)); - Assert.IsNotNull (loaded.Where (v => v.Id == customers[1].Id)); - Assert.IsNotNull (loaded.Where (v => v.Id == customers[2].Id)); - Assert.IsNotNull (loaded.Where (v => v.Id == customers[3].Id)); - Assert.IsNotNull (loaded.Where (v => v.Id == customers[4].Id)); - } - - [Test] - public void TestExecuteAsync () - { - // connect... - string path = null; - var conn = GetConnection (ref path); - conn.CreateTableAsync ().Wait (); - - // do a manual insert... - string email = Guid.NewGuid ().ToString (); - conn.ExecuteAsync ("insert into customer (firstname, lastname, email) values (?, ?, ?)", - "foo", "bar", email).Wait (); - - // check... - using (SQLiteConnection check = new SQLiteConnection (path)) { - // load it back - should be null... - var result = check.Table ().Where (v => v.Email == email); - Assert.IsNotNull (result); - } - } - - [Test] - public void TestInsertAllAsync () - { - // create a bunch of customers... - List customers = new List (); - for (int index = 0; index < 100; index++) { - Customer customer = new Customer (); - customer.FirstName = "foo"; - customer.LastName = "bar"; - customer.Email = Guid.NewGuid ().ToString (); - customers.Add (customer); - } - - // connect... - string path = null; - var conn = GetConnection (ref path); - conn.CreateTableAsync ().Wait (); - - // insert them all... - conn.InsertAllAsync (customers).Wait (); - - // check... - using (SQLiteConnection check = new SQLiteConnection (path)) { - for (int index = 0; index < customers.Count; index++) { - // load it back and check... - Customer loaded = check.Get (customers[index].Id); - Assert.AreEqual (loaded.Email, customers[index].Email); - } - } - } - - [Test] - public void TestRunInTransactionAsync () - { - // connect... - string path = null; - var conn = GetConnection (ref path); - conn.CreateTableAsync ().Wait (); - bool transactionCompleted = false; - - // run... - Customer customer = new Customer (); - conn.RunInTransactionAsync ((c) => { - // insert... - customer.FirstName = "foo"; - customer.LastName = "bar"; - customer.Email = Guid.NewGuid ().ToString (); - c.Insert (customer); - - // delete it again... - c.Execute ("delete from customer where id=?", customer.Id); - - // set completion flag - transactionCompleted = true; - }).Wait (10000); - - // check... - Assert.IsTrue(transactionCompleted); - using (SQLiteConnection check = new SQLiteConnection (path)) { - // load it back and check - should be deleted... - var loaded = check.Table ().Where (v => v.Id == customer.Id).ToList (); - Assert.AreEqual (0, loaded.Count); - } - } - - [Test] - public void TestExecuteScalar () - { - // connect... - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - - // check... - var task = conn.ExecuteScalarAsync ("select name from sqlite_master where type='table' and name='customer'"); - task.Wait (); - object name = task.Result; - Assert.AreNotEqual ("Customer", name); - } - - [Test] - public void TestAsyncTableQueryToListAsync () - { - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - - // create... - Customer customer = this.CreateCustomer (); - conn.InsertAsync (customer).Wait (); - - // query... - var query = conn.Table (); - var task = query.ToListAsync (); - task.Wait (); - var items = task.Result; - - // check... - var loaded = items.Where (v => v.Id == customer.Id).First (); - Assert.AreEqual (customer.Email, loaded.Email); - } - - [Test] - public void TestAsyncTableQueryToFirstAsyncFound () - { - var conn = GetConnection (); - conn.CreateTableAsync().Wait(); - - // create... - Customer customer = this.CreateCustomer(); - conn.InsertAsync(customer).Wait(); - - // query... - var query = conn.Table ().Where(v => v.Id == customer.Id); - var task = query.FirstAsync (); - task.Wait(); - var loaded = task.Result; - - // check... - Assert.AreEqual(customer.Email, loaded.Email); - } - - [Test] - public void TestAsyncTableQueryToFirstAsyncMissing () - { - var conn = GetConnection(); - conn.CreateTableAsync().Wait(); - - // create... - Customer customer = this.CreateCustomer(); - conn.InsertAsync(customer).Wait(); - - // query... - var query = conn.Table().Where(v => v.Id == -1); - var task = query.FirstAsync(); - ExceptionAssert.Throws(() => task.Wait()); - } - - [Test] - public void TestAsyncTableQueryToFirstOrDefaultAsyncFound () - { - var conn = GetConnection(); - conn.CreateTableAsync().Wait(); - - // create... - Customer customer = this.CreateCustomer(); - conn.InsertAsync(customer).Wait(); - - // query... - var query = conn.Table().Where(v => v.Id == customer.Id); - var task = query.FirstOrDefaultAsync(); - task.Wait(); - var loaded = task.Result; - - // check... - Assert.AreEqual(customer.Email, loaded.Email); - } - - [Test] - public void TestAsyncTableQueryToFirstOrDefaultAsyncMissing () - { - var conn = GetConnection(); - conn.CreateTableAsync().Wait(); - - // create... - Customer customer = this.CreateCustomer(); - conn.InsertAsync(customer).Wait(); - - // query... - var query = conn.Table().Where(v => v.Id == -1); - var task = query.FirstOrDefaultAsync(); - task.Wait(); - var loaded = task.Result; - - // check... - Assert.IsNull(loaded); - } - - [Test] - public void TestAsyncTableQueryWhereOperation () - { - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - - // create... - Customer customer = this.CreateCustomer (); - conn.InsertAsync (customer).Wait (); - - // query... - var query = conn.Table (); - var task = query.ToListAsync (); - task.Wait (); - var items = task.Result; - - // check... - var loaded = items.Where (v => v.Id == customer.Id).First (); - Assert.AreEqual (customer.Email, loaded.Email); - } - - [Test] - public void TestAsyncTableQueryCountAsync () - { - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - conn.ExecuteAsync ("delete from customer").Wait (); - - // create... - for (int index = 0; index < 10; index++) - conn.InsertAsync (this.CreateCustomer ()).Wait (); - - // load... - var query = conn.Table (); - var task = query.CountAsync (); - task.Wait (); - - // check... - Assert.AreEqual (10, task.Result); - } - - [Test] - public void TestAsyncTableOrderBy () - { - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - conn.ExecuteAsync ("delete from customer").Wait (); - - // create... - for (int index = 0; index < 10; index++) - conn.InsertAsync (this.CreateCustomer ()).Wait (); - - // query... - var query = conn.Table ().OrderBy (v => v.Email); - var task = query.ToListAsync (); - task.Wait (); - var items = task.Result; - - // check... - Assert.AreEqual (-1, string.Compare (items[0].Email, items[9].Email)); - } - - [Test] - public void TestAsyncTableOrderByDescending () - { - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - conn.ExecuteAsync ("delete from customer").Wait (); - - // create... - for (int index = 0; index < 10; index++) - conn.InsertAsync (this.CreateCustomer ()).Wait (); - - // query... - var query = conn.Table ().OrderByDescending (v => v.Email); - var task = query.ToListAsync (); - task.Wait (); - var items = task.Result; - - // check... - Assert.AreEqual (1, string.Compare (items[0].Email, items[9].Email)); - } - - [Test] - public void TestAsyncTableQueryTake () - { - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - conn.ExecuteAsync ("delete from customer").Wait (); - - // create... - for (int index = 0; index < 10; index++) { - var customer = this.CreateCustomer (); - customer.FirstName = index.ToString (); - conn.InsertAsync (customer).Wait (); - } - - // query... - var query = conn.Table ().OrderBy (v => v.FirstName).Take (1); - var task = query.ToListAsync (); - task.Wait (); - var items = task.Result; - - // check... - Assert.AreEqual (1, items.Count); - Assert.AreEqual ("0", items[0].FirstName); - } - - [Test] - public void TestAsyncTableQuerySkip () - { - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - conn.ExecuteAsync ("delete from customer").Wait (); - - // create... - for (int index = 0; index < 10; index++) { - var customer = this.CreateCustomer (); - customer.FirstName = index.ToString (); - conn.InsertAsync (customer).Wait (); - } - - // query... - var query = conn.Table ().OrderBy (v => v.FirstName).Skip (5); - var task = query.ToListAsync (); - task.Wait (); - var items = task.Result; - - // check... - Assert.AreEqual (5, items.Count); - Assert.AreEqual ("5", items[0].FirstName); - } - - [Test] - public void TestAsyncTableElementAtAsync () - { - var conn = GetConnection (); - conn.CreateTableAsync ().Wait (); - conn.ExecuteAsync ("delete from customer").Wait (); - - // create... - for (int index = 0; index < 10; index++) { - var customer = this.CreateCustomer (); - customer.FirstName = index.ToString (); - conn.InsertAsync (customer).Wait (); - } - - // query... - var query = conn.Table ().OrderBy (v => v.FirstName); - var task = query.ElementAtAsync (7); - task.Wait (); - var loaded = task.Result; - - // check... - Assert.AreEqual ("7", loaded.FirstName); - } - - - [Test] - public void TestAsyncGetWithExpression() - { - var conn = GetConnection(); - conn.CreateTableAsync().Wait(); - conn.ExecuteAsync("delete from customer").Wait(); + // @mbrit - 2012-05-14 - NOTE - the lack of async use in this class is because the VS11 test runner falsely + // reports any failing test as succeeding if marked as async. Should be fixed in the "June 2012" drop... + + public class Customer + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + [MaxLength(64)] + public string FirstName { get; set; } + + [MaxLength(64)] + public string LastName { get; set; } + + [MaxLength(64)] + public string Email { get; set; } + } + + /// + /// Defines tests that exercise async behaviour. + /// + [TestFixture] + public class AsyncTests + { + [SetUp] + public void SetUp() + { + if (_sqliteConnectionPool != null) + { + _sqliteConnectionPool.Reset(); + } + _path = Path.Combine(Path.GetTempPath(), DatabaseName); + // delete old db file + File.Delete(_path); + + _connectionParameters = new SQLiteConnectionString(_path, false); + _sqliteConnectionPool = new SQLiteConnectionPool(_sqlite3Platform); + } + + private const string DatabaseName = "async.db"; + + private SQLiteAsyncConnection GetConnection() + { + string path = null; + return GetConnection(ref path); + } + + private string _path; + private SQLiteConnectionString _connectionParameters; + private SQLitePlatformTest _sqlite3Platform; + private SQLiteConnectionPool _sqliteConnectionPool; + + [TestFixtureSetUp] + public void TestFixtureSetUp() + { + _sqlite3Platform = new SQLitePlatformTest(); + _sqliteConnectionPool = new SQLiteConnectionPool(_sqlite3Platform); + } + + private SQLiteAsyncConnection GetConnection(ref string path) + { + path = _path; + return new SQLiteAsyncConnection(() => _sqliteConnectionPool.GetConnection(_connectionParameters)); + } + + private Customer CreateCustomer() + { + var customer = new Customer + { + FirstName = "foo", + LastName = "bar", + Email = Guid.NewGuid().ToString() + }; + return customer; + } + + [Test] + public async Task FindAsyncWithExpression() + { + // create... + var customer = new Customer(); + customer.FirstName = "foo"; + customer.LastName = "bar"; + customer.Email = Guid.NewGuid().ToString(); + + // connect and insert... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + await conn.InsertAsync(customer); + + // check... + Assert.AreNotEqual(0, customer.Id); + + // get it back... + var loaded = await conn.FindAsync(x => x.Id == customer.Id); + + // check... + Assert.AreEqual(customer.Id, loaded.Id); + } + + [Test] + public async Task FindAsyncWithExpressionNull() + { + // connect and insert... + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + + // get it back... + var loaded = await conn.FindAsync(x => x.Id == 1); + + // check... + Assert.IsNull(loaded); + } + + [Test] + public async Task GetAsync() + { + // create... + var customer = new Customer(); + customer.FirstName = "foo"; + customer.LastName = "bar"; + customer.Email = Guid.NewGuid().ToString(); + + // connect and insert... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + await conn.InsertAsync(customer); + + // check... + Assert.AreNotEqual(0, customer.Id); + + // get it back... + var loaded = await conn.GetAsync(customer.Id); + + // check... + Assert.AreEqual(customer.Id, loaded.Id); + } + + [Test] + public async Task StressAsync() + { + string path = null; + SQLiteAsyncConnection globalConn = GetConnection(ref path); + + await globalConn.CreateTableAsync(); + + int n = 500; + var errors = new ConcurrentBag(); + var tasks = new List(); + for (int i = 0; i < n; i++) + { + int i1 = i; + tasks.Add(Task.Factory.StartNew(async delegate + { + try + { + SQLiteAsyncConnection conn = GetConnection(); + var obj = new Customer + { + FirstName = i1.ToString(), + }; + await conn.InsertAsync(obj); + if (obj.Id == 0) + { + errors.Add("Bad id"); + } + var obj3 = await (from c in conn.Table() where c.Id == obj.Id select c).ToListAsync(); + Customer obj2 = obj3.FirstOrDefault(); + if (obj2 == null) + { + errors.Add("Failed query"); + } + } + catch (Exception ex) + { + errors.Add(ex.Message); + } + })); + } + + await Task.WhenAll(tasks); + int count = await globalConn.Table().CountAsync(); + + Assert.AreEqual(0, errors.Count); + Assert.AreEqual(n, count); + } + + [Test] + public async Task TestAsyncGetWithExpression() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + await conn.ExecuteAsync("delete from customer"); // create... for (int index = 0; index < 10; index++) { - var customer = this.CreateCustomer(); + Customer customer = CreateCustomer(); customer.FirstName = index.ToString(); - conn.InsertAsync(customer).Wait(); + await conn.InsertAsync(customer); } // get... - var result = conn.GetAsync(x => x.FirstName == "7"); - result.Wait(); - var loaded = result.Result; + var loaded = await conn.GetAsync(x => x.FirstName == "7"); // check... Assert.AreEqual("7", loaded.FirstName); } - } -} + + [Test] + public async Task TestAsyncTableElementAtAsync() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + await conn.ExecuteAsync("delete from customer"); + + // create... + for (int index = 0; index < 10; index++) + { + Customer customer = CreateCustomer(); + customer.FirstName = index.ToString(); + await conn.InsertAsync(customer); + } + + // query... + AsyncTableQuery query = conn.Table().OrderBy(v => v.FirstName); + var loaded = await query.ElementAtAsync(7); + + // check... + Assert.AreEqual("7", loaded.FirstName); + } + + [Test] + public async Task TestAsyncTableOrderBy() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + await conn.ExecuteAsync("delete from customer"); + + // create... + for (int index = 0; index < 10; index++) + { + await conn.InsertAsync(CreateCustomer()); + } + + // query... + AsyncTableQuery query = conn.Table().OrderBy(v => v.Email); + var items = await query.ToListAsync(); + + // check... + Assert.AreEqual(-1, string.Compare(items[0].Email, items[9].Email)); + } + + [Test] + public async Task TestAsyncTableOrderByDescending() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + await conn.ExecuteAsync("delete from customer"); + + // create... + for (int index = 0; index < 10; index++) + { + await conn.InsertAsync(CreateCustomer()); + } + + // query... + AsyncTableQuery query = conn.Table().OrderByDescending(v => v.Email); + var items = await query.ToListAsync(); + + // check... + Assert.AreEqual(1, string.Compare(items[0].Email, items[9].Email)); + } + + [Test] + public async Task TestAsyncTableThenBy() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + await conn.ExecuteAsync("delete from customer"); + + // create... + for (int index = 0; index < 10; index++) + { + await conn.InsertAsync(CreateCustomer()); + } + var preceedingFirstNameCustomer = CreateCustomer(); + preceedingFirstNameCustomer.FirstName = "a" + preceedingFirstNameCustomer.FirstName; + await conn.InsertAsync(preceedingFirstNameCustomer); + + // query... + AsyncTableQuery query = conn.Table().OrderBy(v => v.FirstName).ThenBy(v => v.Email); + var items = await query.ToListAsync(); + + // check... + var list = (await conn.Table().ToListAsync()).OrderBy(v => v.FirstName).ThenBy(v => v.Email).ToList(); + for (var i = 0; i < list.Count; i++) + Assert.AreEqual(list[i].Email, items[i].Email); + } + + [Test] + public async Task TestAsyncTableThenByDescending() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + await conn.ExecuteAsync("delete from customer"); + + // create... + for (int index = 0; index < 10; index++) + { + await conn.InsertAsync(CreateCustomer()); + } + var preceedingFirstNameCustomer = CreateCustomer(); + preceedingFirstNameCustomer.FirstName = "a" + preceedingFirstNameCustomer.FirstName; + await conn.InsertAsync(preceedingFirstNameCustomer); + + // query... + AsyncTableQuery query = conn.Table().OrderBy(v => v.FirstName).ThenByDescending(v => v.Email); + var items = await query.ToListAsync(); + + + // check... + var list = (await conn.Table().ToListAsync()).OrderBy(v => v.FirstName).ThenByDescending(v => v.Email).ToList(); + for (var i = 0; i < list.Count; i++) + Assert.AreEqual(list[i].Email, items[i].Email); + } + + [Test] + public async Task TestAsyncTableQueryCountAsync() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + await conn.ExecuteAsync("delete from customer"); + + // create... + for (int index = 0; index < 10; index++) + { + await conn.InsertAsync(CreateCustomer()); + } + + // load... + AsyncTableQuery query = conn.Table(); + var result = await query.CountAsync(); + + // check... + Assert.AreEqual(10, result); + } + + [Test] + public async Task TestAsyncTableQuerySkip() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + await conn.ExecuteAsync("delete from customer"); + + // create... + for (int index = 0; index < 10; index++) + { + Customer customer = CreateCustomer(); + customer.FirstName = index.ToString(); + await conn.InsertAsync(customer); + } + + // query... + AsyncTableQuery query = conn.Table().OrderBy(v => v.FirstName).Skip(5); + var items = await query.ToListAsync(); + + // check... + Assert.AreEqual(5, items.Count); + Assert.AreEqual("5", items[0].FirstName); + } + + [Test] + public async Task TestAsyncTableQueryTake() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + await conn.ExecuteAsync("delete from customer"); + + // create... + for (int index = 0; index < 10; index++) + { + Customer customer = CreateCustomer(); + customer.FirstName = index.ToString(); + await conn.InsertAsync(customer); + } + + // query... + AsyncTableQuery query = conn.Table().OrderBy(v => v.FirstName).Take(1); + var items = await query.ToListAsync(); + + // check... + Assert.AreEqual(1, items.Count); + Assert.AreEqual("0", items[0].FirstName); + } + + [Test] + public async Task TestAsyncTableQueryToFirstAsyncFound() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + + // create... + Customer customer = CreateCustomer(); + await conn.InsertAsync(customer); + + // query... + AsyncTableQuery query = conn.Table().Where(v => v.Id == customer.Id); + var loaded = await query.FirstAsync(); + + // check... + Assert.AreEqual(customer.Email, loaded.Email); + } + + [Test] + public async Task TestAsyncTableQueryToFirstAsyncMissing() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + + // create... + Customer customer = CreateCustomer(); + await conn.InsertAsync(customer); + + // query... + AsyncTableQuery query = conn.Table().Where(v => v.Id == -1); + Assert.That(async () => await query.FirstAsync(), Throws.TypeOf()); + } + + [Test] + public async Task TestAsyncTableQueryToFirstOrDefaultAsyncFound() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + + // create... + Customer customer = CreateCustomer(); + await conn.InsertAsync(customer); + + // query... + AsyncTableQuery query = conn.Table().Where(v => v.Id == customer.Id); + Customer loaded = await query.FirstOrDefaultAsync(); + + // check... + Assert.AreEqual(customer.Email, loaded.Email); + } + + [Test] + public async Task TestAsyncTableQueryToFirstOrDefaultAsyncMissing() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + + // create... + Customer customer = CreateCustomer(); + await conn.InsertAsync(customer); + + // query... + AsyncTableQuery query = conn.Table().Where(v => v.Id == -1); + Customer loaded = await query.FirstOrDefaultAsync(); + + // check... + Assert.IsNull(loaded); + } + + [Test] + public async Task TestAsyncTableQueryToListAsync() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + + // create... + Customer customer = CreateCustomer(); + await conn.InsertAsync(customer); + + // query... + AsyncTableQuery query = conn.Table(); + List items = await query.ToListAsync(); + + // check... + Customer loaded = items.Where(v => v.Id == customer.Id).First(); + Assert.AreEqual(customer.Email, loaded.Email); + } + + [Test] + public async Task TestAsyncTableQueryWhereOperation() + { + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + + // create... + Customer customer = CreateCustomer(); + await conn.InsertAsync(customer); + + // query... + AsyncTableQuery query = conn.Table(); + var items = await query.ToListAsync(); + + // check... + Customer loaded = items.Where(v => v.Id == customer.Id).First(); + Assert.AreEqual(customer.Email, loaded.Email); + } + + [Test] + public async Task TestCreateTableAsync() + { + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + + // drop the customer table... + await conn.ExecuteAsync("drop table if exists Customer"); + + // run... + await conn.CreateTableAsync(); + + // check... + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + // run it - if it's missing we'll get a failure... + check.Execute("select * from Customer"); + } + } + + [Test] + public async Task TestDeleteAsync() + { + // create... + Customer customer = CreateCustomer(); + + // connect... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + + // run... + await conn.InsertAsync(customer); + + // delete it... + await conn.DeleteAsync(customer); + + // check... + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + // load it back - should be null... + List loaded = check.Table().Where(v => v.Id == customer.Id).ToList(); + Assert.AreEqual(0, loaded.Count); + } + } + + [Test] + public async Task TestDropTableAsync() + { + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + + // drop it... + await conn.DropTableAsync(); + + // check... + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + // load it back and check - should be missing + SQLiteCommand command = + check.CreateCommand("select name from sqlite_master where type='table' and name='customer'"); + Assert.IsNull(command.ExecuteScalar()); + } + } + + [Test] + public async Task TestExecuteAsync() + { + // connect... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + + // do a manual insert... + string email = Guid.NewGuid().ToString(); + await conn.ExecuteAsync("insert into customer (firstname, lastname, email) values (?, ?, ?)", + "foo", "bar", email); + + // check... + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + // load it back - should be null... + TableQuery result = check.Table().Where(v => v.Email == email); + Assert.IsNotNull(result); + } + } + + [Test] + public async Task TestExecuteScalar() + { + // connect... + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + + // check... + object name = await conn.ExecuteScalarAsync("select name from sqlite_master where type='table' and name='customer'"); + Assert.AreNotEqual("Customer", name); + } + + [Test] + public async Task TestFindAsyncItemMissing() + { + // connect and insert... + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + + // now get one that doesn't exist... + Task task = conn.FindAsync(-1); + + // check... + Assert.IsNull(await task); + } + + [Test] + public async Task TestFindAsyncItemPresent() + { + // create... + Customer customer = CreateCustomer(); + + // connect and insert... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + await conn.InsertAsync(customer); + + // check... + Assert.AreNotEqual(0, customer.Id); + + // get it back... + Task task = conn.FindAsync(customer.Id); + Customer loaded = await task; + + // check... + Assert.AreEqual(customer.Id, loaded.Id); + } + + [Test] + public async Task TestInsertAllAsync() + { + // create a bunch of customers... + var customers = new List(); + for (int index = 0; index < 100; index++) + { + var customer = new Customer(); + customer.FirstName = "foo"; + customer.LastName = "bar"; + customer.Email = Guid.NewGuid().ToString(); + customers.Add(customer); + } + + // connect... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + + // insert them all... + await conn.InsertAllAsync(customers); + + // check... + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + for (int index = 0; index < customers.Count; index++) + { + // load it back and check... + var loaded = check.Get(customers[index].Id); + Assert.AreEqual(loaded.Email, customers[index].Email); + } + } + } + + [Test] + public async Task TestInsertAsync() + { + // create... + Customer customer = CreateCustomer(); + + // connect... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + + // run... + await conn.InsertAsync(customer); + + // check that we got an id... + Assert.AreNotEqual(0, customer.Id); + + // check... + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + // load it back... + var loaded = check.Get(customer.Id); + Assert.AreEqual(loaded.Id, customer.Id); + } + } + + [Test] + public async Task TestInsertOrReplaceAllAsync() + { + // create a bunch of customers... + var customers = new List(); + for (int index = 0; index < 100; index++) + { + var customer = new Customer(); + customer.Id = index; + customer.FirstName = "foo"; + customer.LastName = "bar"; + customer.Email = Guid.NewGuid().ToString(); + customers.Add(customer); + } + + // connect... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + + // insert them all... + await conn.InsertOrReplaceAllAsync(customers); + + // change the existing ones... + foreach (var customer in customers) + { + customer.FirstName = "baz"; + customer.LastName = "biz"; + } + + // ... and add a few more + for (int index = 100; index < 200; index++) + { + var customer = new Customer(); + customer.Id = index; + customer.FirstName = "foo"; + customer.LastName = "bar"; + customer.Email = Guid.NewGuid().ToString(); + customers.Add(customer); + } + + // insert them all, replacing the already existing ones + await conn.InsertOrReplaceAllAsync(customers); + + // check... + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + for (int index = 0; index < customers.Count; index++) + { + // load it back and check... + var loaded = check.Get(customers[index].Id); + Assert.AreEqual(loaded.FirstName, customers[index].FirstName); + Assert.AreEqual(loaded.LastName, customers[index].LastName); + Assert.AreEqual(loaded.Email, customers[index].Email); + } + } + + } + + [Test] + public async Task TestInsertOrReplaceAsync() + { + // create... + var customer = new Customer(); + customer.Id = 42; + customer.FirstName = "foo"; + customer.LastName = "bar"; + customer.Email = Guid.NewGuid().ToString(); + + // connect... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + + // run... + await conn.InsertOrReplaceAsync(customer); + + // check... + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + // load it back... + var loaded = check.Get(customer.Id); + Assert.AreEqual(loaded.Id, customer.Id); + Assert.AreEqual(loaded.FirstName, customer.FirstName); + Assert.AreEqual(loaded.LastName, customer.LastName); + Assert.AreEqual(loaded.Email, customer.Email); + } + + // change ... + customer.FirstName = "baz"; + customer.LastName = "biz"; + customer.Email = Guid.NewGuid().ToString(); + + // replace... + await conn.InsertOrReplaceAsync(customer); + + // check again... + // check... + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + // load it back... + var loaded = check.Get(customer.Id); + Assert.AreEqual(loaded.Id, customer.Id); + Assert.AreEqual(loaded.FirstName, customer.FirstName); + Assert.AreEqual(loaded.LastName, customer.LastName); + Assert.AreEqual(loaded.Email, customer.Email); + } + } + + [Test] + public async Task TestQueryAsync() + { + // connect... + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + + // insert some... + var customers = new List(); + for (int index = 0; index < 5; index++) + { + Customer customer = CreateCustomer(); + + // insert... + await conn.InsertAsync(customer); + + // add... + customers.Add(customer); + } + + // return the third one... + List loaded = await conn.QueryAsync("select * from customer where id=?", customers[2].Id); + + // check... + Assert.AreEqual(1, loaded.Count); + Assert.AreEqual(customers[2].Email, loaded[0].Email); + } + + [Test] + public async Task TestRunInTransactionAsync() + { + // connect... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + bool transactionCompleted = false; + + // run... + var customer = new Customer(); + await conn.RunInTransactionAsync(c => + { + // insert... + customer.FirstName = "foo"; + customer.LastName = "bar"; + customer.Email = Guid.NewGuid().ToString(); + c.Insert(customer); + + // delete it again... + c.Execute("delete from customer where id=?", customer.Id); + + // set completion flag + transactionCompleted = true; + }); + + // check... + Assert.IsTrue(transactionCompleted); + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + // load it back and check - should be deleted... + List loaded = check.Table().Where(v => v.Id == customer.Id).ToList(); + Assert.AreEqual(0, loaded.Count); + } + } + + [Test] + public async Task TestTableAsync() + { + // connect... + SQLiteAsyncConnection conn = GetConnection(); + await conn.CreateTableAsync(); + await conn.ExecuteAsync("delete from customer"); + + // insert some... + var customers = new List(); + for (int index = 0; index < 5; index++) + { + var customer = new Customer(); + customer.FirstName = "foo"; + customer.LastName = "bar"; + customer.Email = Guid.NewGuid().ToString(); + + // insert... + await conn.InsertAsync(customer); + + // add... + customers.Add(customer); + } + + // run the table operation... + AsyncTableQuery query = conn.Table(); + List loaded = await query.ToListAsync(); + + // check that we got them all back... + Assert.AreEqual(5, loaded.Count); + Assert.IsNotNull(loaded.Where(v => v.Id == customers[0].Id)); + Assert.IsNotNull(loaded.Where(v => v.Id == customers[1].Id)); + Assert.IsNotNull(loaded.Where(v => v.Id == customers[2].Id)); + Assert.IsNotNull(loaded.Where(v => v.Id == customers[3].Id)); + Assert.IsNotNull(loaded.Where(v => v.Id == customers[4].Id)); + } + + [Test] + public async Task TestUpdateAsync() + { + // create... + Customer customer = CreateCustomer(); + + // connect... + string path = null; + SQLiteAsyncConnection conn = GetConnection(ref path); + await conn.CreateTableAsync(); + + // run... + await conn.InsertAsync(customer); + + // change it... + string newEmail = Guid.NewGuid().ToString(); + customer.Email = newEmail; + + // save it... + await conn.UpdateAsync(customer); + + // check... + using (var check = new SQLiteConnection(_sqlite3Platform, path)) + { + // load it back - should be changed... + var loaded = check.Get(customer.Id); + Assert.AreEqual(newEmail, loaded.Email); + } + } + } +} \ No newline at end of file diff --git a/tests/BlobSerializationTest.cs b/tests/BlobSerializationTest.cs new file mode 100644 index 000000000..0aaeb8a99 --- /dev/null +++ b/tests/BlobSerializationTest.cs @@ -0,0 +1,391 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; +#endif + +#if WINDOWS_PHONE +using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; +using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; +using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; +#else +using NUnit.Framework; +using SQLite.Net.Interop; +using SQLite.Net.Attributes; +#endif + +namespace SQLite.Net.Tests +{ + //[TestFixture] + public abstract class BlobSerializationTest + { + protected abstract IBlobSerializer Serializer { get; } + + public class BlobDatabase : SQLiteConnection + { + public BlobDatabase(IBlobSerializer serializer) : + base(new SQLitePlatformTest(), TestPath.GetTempFileName(), false, serializer) + { + DropTable(); + } + } + + public class ComplexOrder : IEquatable + { + public ComplexOrder() + { + PlacedTime = DateTime.UtcNow; + History = new List(); + Lines = new List(); + } + + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public DateTime PlacedTime { get; set; } + + public List History { get; set; } + + public List Lines { get; set; } + + public override bool Equals(object obj) + { + return this.Equals(obj as ComplexOrder); + } + + public override int GetHashCode() + { + return this.Id.GetHashCode() ^ + //this.PlacedTime.GetHashCode() ^ + this.History.GetHashCode() ^ + this.Lines.GetHashCode(); + } + + public bool Equals(ComplexOrder other) + { + if (other == null) + { + return false; + } + + return this.Id.Equals(other.Id) && + Math.Abs((this.PlacedTime - other.PlacedTime).TotalMilliseconds) < 100 && + this.History.SequenceEqual(other.History) && + this.Lines.SequenceEqual(other.Lines); + } + } + + public class ComplexHistory : IEquatable + { + public DateTime Time { get; set; } + public string Comment { get; set; } + + public override int GetHashCode() + { + return this.Comment.GetHashCode(); + } + + public override bool Equals(object obj) + { + return this.Equals(obj as ComplexHistory); + } + + public bool Equals(ComplexHistory other) + { + if (other == null) + { + return false; + } + + return this.Comment.Equals(other.Comment); + } + } + + public class ComplexLine : IEquatable + { + [Indexed("IX_OrderProduct", 2)] + public int ProductId { get; set; } + + public int Quantity { get; set; } + public decimal UnitPrice { get; set; } + public OrderLineStatus Status { get; set; } + + public override bool Equals(object obj) + { + return this.Equals(obj as ComplexLine); + } + + public override int GetHashCode() + { + return + this.ProductId.GetHashCode() ^ + this.Quantity.GetHashCode() ^ + this.Status.GetHashCode() ^ + this.UnitPrice.GetHashCode(); + } + + public bool Equals(ComplexLine other) + { + if (other == null) + { + return false; + } + + return + this.ProductId.Equals(other.ProductId) && + this.Quantity.Equals(other.Quantity) && + this.Status.Equals(other.Status) && + this.UnitPrice.Equals(other.UnitPrice); + } + } + + [Test] + public void VerifyTableCreationFailsWithNoSerializer() + { + NotSupportedException ex = null; + using (var db = new BlobDatabase(null)) + { + try + { + var count = db.CreateTable(); + Assert.IsTrue(count == 0); + Assert.IsNull(db.GetMapping()); + return; + } + catch (NotSupportedException e) + { + ex = e; + } + } + + Assert.IsNotNull(ex); + } + + [Test] + public void VerifyTableCreationSucceedsWithSupportedSerializer() + { + if (!this.Serializer.CanDeserialize(typeof(ComplexOrder))) + { + Assert.Ignore("Serialize does not support this data type"); + } + + using (var db = new BlobDatabase(this.Serializer)) + { + db.CreateTable(); + var mapping = db.GetMapping(); + Assert.IsNotNull(mapping); + Assert.AreEqual(4, mapping.Columns.Length); + } + } + + //[Test] + public void TestListOfObjects() + { + if (!this.Serializer.CanDeserialize(typeof(ComplexOrder))) + { + Assert.Ignore("Serialize does not support this data type"); + } + + using (var db = new BlobDatabase(this.Serializer)) + { + db.CreateTable(); + var order = new ComplexOrder(); + + var count = db.Insert(order); + Assert.AreEqual(count, 1); + var orderCopy = db.Find(order.Id); + Assert.AreEqual(order, orderCopy); + + for (var n = 0; n < 10; ) + { + order.Lines.Add(new ComplexLine() { ProductId = 1, Quantity = ++n, Status = OrderLineStatus.Placed, UnitPrice = (n / 10m) }); + db.Update(order); + orderCopy = db.Find(order.Id); + Assert.AreEqual(order, orderCopy); + order.History.Add(new ComplexHistory() { Time = DateTime.UtcNow, Comment = string.Format("New history {0}", n) }); + db.Update(order); + orderCopy = db.Find(order.Id); + Assert.AreEqual(order, orderCopy); + } + } + } + } + + [TestFixture] + public class BlobDelegateTest : BlobSerializationTest + { + public enum Bool { True, False } + + public class SupportedTypes + { + public Boolean Boolean { get; set; } + public Byte Byte { get; set; } + public UInt16 UInt16 { get; set; } + public SByte SByte { get; set; } + public Int16 Int16 { get; set; } + public Int32 Int32 { get; set; } + public UInt32 UInt32{ get; set; } + public Int64 Int64{ get; set; } + public Single Single { get; set; } + public Double Double { get; set; } + public Decimal Decimal { get; set; } + public String String{ get; set; } + public DateTime DateTime{ get; set; } + public Bool EnumBool{ get; set; } + public Guid Guid{ get; set; } + public byte[] Bytes{ get; set; } + public TimeSpan Timespan { get; set; } + } + + public class UnsupportedTypes + { + [PrimaryKey] + public Guid Id { get; set; } + + + public DateTimeOffset DateTimeOffset { get; set; } + } + + protected override IBlobSerializer Serializer + { + get + { + return new BlobSerializerDelegate( + obj => new byte[0], + (data, type) => null, + type => false); + } + } + + [Test] + public void CanDeserializeIsRequested() + { + var types = new List(); + + var serializer = new BlobSerializerDelegate(obj => null, (d, t) => null, t => + { + types.Add(t); + return true; + }); + + using (var db = new BlobDatabase(serializer)) + { + db.CreateTable(); + } + + Assert.That(types, Has.Member(typeof (List))); + Assert.That(types, Has.Member(typeof (List))); + + Assert.AreEqual(2, types.Count, "Too many types requested by serializer"); + } + + [Test] + public void DoesNotCallOnSupportedTypes() + { + var types = new List(); + + var serializer = new BlobSerializerDelegate(obj => null, (d, t) => null, t => + { + throw new InvalidOperationException(string.Format("Type {0} should not be requested.", t)); + }); + + using (var db = new BlobDatabase(serializer)) + { + db.CreateTable(); + } + + Assert.AreEqual(0, types.Count, "Types requested from serializer"); + } + + [Test] + public void CallsOnUnsupportedTypes() + { + var types = new List(); + + var serializer = new BlobSerializerDelegate(obj => null, (d, t) => null, t => + { + types.Add(t); + return true; + }); + + using (var db = new BlobDatabase(serializer)) + { + db.CreateTable(); + } + + Assert.That(types, Has.Member(typeof (DateTimeOffset))); + + Assert.AreEqual(1, types.Count, "Too many types requested by serializer"); + } + + [Test] + public void SavesUnsupportedTypes() + { + UnsupportedTypes item = null; + + var serializer = new BlobSerializerDelegate( + obj => + { + if (obj is DateTimeOffset) + { + Assert.AreEqual(item.DateTimeOffset, obj); + var offset = (DateTimeOffset)obj; + var bytes = new byte[16]; + Buffer.BlockCopy(BitConverter.GetBytes(offset.Ticks), 0, bytes, 0, 8); + Buffer.BlockCopy(BitConverter.GetBytes(offset.Offset.Ticks), 0, bytes, 8, 8); + return bytes; + } + + throw new InvalidOperationException(string.Format("Type {0} should not be requested.", obj.GetType())); + }, + (d, t) => + { + if (t == typeof(DateTimeOffset)) + { + var ticks = BitConverter.ToInt64(d, 0); + var offset = BitConverter.ToInt64(d, 8); + return new DateTimeOffset(ticks, TimeSpan.FromTicks(offset)); + } + + if (t == typeof(TimeSpan)) + { + return TimeSpan.FromTicks(BitConverter.ToInt64(d, 0)); + } + + throw new InvalidOperationException(string.Format("Type {0} should not be requested.", t)); + }, + t => true); + + using (var db = new BlobDatabase(serializer)) + { + db.CreateTable(); + item = new UnsupportedTypes() + { + Id = Guid.NewGuid(), + DateTimeOffset = DateTime.Now + }; + + db.Insert(item); + var dbItem = db.Find(item.Id); + + Assert.AreEqual(item.Id, dbItem.Id); + Assert.AreEqual(item.DateTimeOffset, dbItem.DateTimeOffset); + } + } + } +} diff --git a/tests/BooleanTest.cs b/tests/BooleanTest.cs index ec499977d..1e28e133b 100644 --- a/tests/BooleanTest.cs +++ b/tests/BooleanTest.cs @@ -1,24 +1,25 @@ using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SQLite; - using System.Diagnostics; +using NUnit.Framework; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; #else -using NUnit.Framework; +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif - -namespace SQLite.Tests -{ +namespace SQLite.Net.Tests +{ [TestFixture] public class BooleanTest { @@ -26,6 +27,7 @@ public class VO { [AutoIncrement, PrimaryKey] public int ID { get; set; } + public bool Flag { get; set; } public String Text { get; set; } @@ -34,11 +36,13 @@ public override string ToString() return string.Format("VO:: ID:{0} Flag:{1} Text:{2}", ID, Flag, Text); } } + public class DbAcs : SQLiteConnection { - public DbAcs(String path) - : base(path) + public DbAcs(ISQLitePlatform sqlitePlatform, String path) + : base(sqlitePlatform, path) { + TraceListener = DebugTraceListener.Instance; } public void buildTable() @@ -48,31 +52,42 @@ public void buildTable() public int CountWithFlag(Boolean flag) { - var cmd = CreateCommand("SELECT COUNT(*) FROM VO Where Flag = ?", flag); - return cmd.ExecuteScalar(); + SQLiteCommand cmd = CreateCommand("SELECT COUNT(*) FROM VO Where Flag = ?", flag); + return cmd.ExecuteScalar(); } } - + [Test] public void TestBoolean() { - var tmpFile = TestPath.GetTempFileName(); - var db = new DbAcs(tmpFile); + var sqlite3Platform = new SQLitePlatformTest(); + string tmpFile = TestPath.GetTempFileName(); + var db = new DbAcs(sqlite3Platform, tmpFile); db.buildTable(); for (int i = 0; i < 10; i++) - db.Insert(new VO() { Flag = (i % 3 == 0), Text = String.Format("VO{0}", i) }); - + { + db.Insert(new VO + { + Flag = (i%3 == 0), + Text = String.Format("VO{0}", i) + }); + } + // count vo which flag is true Assert.AreEqual(4, db.CountWithFlag(true)); Assert.AreEqual(6, db.CountWithFlag(false)); Debug.WriteLine("VO with true flag:"); - foreach (var vo in db.Query("SELECT * FROM VO Where Flag = ?", true)) - Debug.WriteLine (vo.ToString ()); + foreach (VO vo in db.Query("SELECT * FROM VO Where Flag = ?", true)) + { + Debug.WriteLine(vo.ToString()); + } - Debug.WriteLine ("VO with false flag:"); - foreach (var vo in db.Query("SELECT * FROM VO Where Flag = ?", false)) - Debug.WriteLine (vo.ToString ()); + Debug.WriteLine("VO with false flag:"); + foreach (VO vo in db.Query("SELECT * FROM VO Where Flag = ?", false)) + { + Debug.WriteLine(vo.ToString()); + } } } -} +} \ No newline at end of file diff --git a/tests/ByteArrayTest.cs b/tests/ByteArrayTest.cs index 2ad4c84d9..db8d41e02 100644 --- a/tests/ByteArrayTest.cs +++ b/tests/ByteArrayTest.cs @@ -1,105 +1,221 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SQLite; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else +using System.Linq; using NUnit.Framework; +using SQLite.Net.Attributes; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif - -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class ByteArrayTest - { - public class ByteArrayClass - { - [PrimaryKey, AutoIncrement] - public int ID { get; set; } - - public byte[] bytes { get; set; } - - public void AssertEquals(ByteArrayClass other) - { - Assert.AreEqual(other.ID, ID); - if (other.bytes == null || bytes == null) { - Assert.IsNull (other.bytes); - Assert.IsNull (bytes); - } - else { - Assert.AreEqual(other.bytes.Length, bytes.Length); - for (var i = 0; i < bytes.Length; i++) { - Assert.AreEqual(other.bytes[i], bytes[i]); - } - } - } - } - - [Test] - [Description("Create objects with various byte arrays and check they can be stored and retrieved correctly")] - public void ByteArrays() - { - //Byte Arrays for comparisson - ByteArrayClass[] byteArrays = new ByteArrayClass[] { - new ByteArrayClass() { bytes = new byte[] { 1, 2, 3, 4, 250, 252, 253, 254, 255 } }, //Range check - new ByteArrayClass() { bytes = new byte[] { 0 } }, //null bytes need to be handled correctly - new ByteArrayClass() { bytes = new byte[] { 0, 0 } }, - new ByteArrayClass() { bytes = new byte[] { 0, 1, 0 } }, - new ByteArrayClass() { bytes = new byte[] { 1, 0, 1 } }, - new ByteArrayClass() { bytes = new byte[] { } }, //Empty byte array should stay empty (and not become null) - new ByteArrayClass() { bytes = null } //Null should be supported - }; - - SQLiteConnection database = new SQLiteConnection(TestPath.GetTempFileName()); - database.CreateTable(); - - //Insert all of the ByteArrayClass - foreach (ByteArrayClass b in byteArrays) - database.Insert(b); - - //Get them back out - ByteArrayClass[] fetchedByteArrays = database.Table().OrderBy(x => x.ID).ToArray(); - - Assert.AreEqual(fetchedByteArrays.Length, byteArrays.Length); - //Check they are the same - for (int i = 0; i < byteArrays.Length; i++) - { - byteArrays[i].AssertEquals(fetchedByteArrays[i]); - } - } - - [Test] - [Description("Create A large byte array and check it can be stored and retrieved correctly")] - public void LargeByteArray() - { - const int byteArraySize = 1024 * 1024; - byte[] bytes = new byte[byteArraySize]; - for (int i = 0; i < byteArraySize; i++) - bytes[i] = (byte)(i % 256); - - ByteArrayClass byteArray = new ByteArrayClass() { bytes = bytes }; - - SQLiteConnection database = new SQLiteConnection(TestPath.GetTempFileName()); - database.CreateTable(); - - //Insert the ByteArrayClass - database.Insert(byteArray); - - //Get it back out - ByteArrayClass[] fetchedByteArrays = database.Table().ToArray(); - - Assert.AreEqual(fetchedByteArrays.Length, 1); - - //Check they are the same - byteArray.AssertEquals(fetchedByteArrays[0]); - } - } -} + [TestFixture] + public class ByteArrayTest + { + [SetUp] + public void SetUp() + { + _sqlite3Platform = new SQLitePlatformTest(); + } + + private SQLitePlatformTest _sqlite3Platform; + + public class ByteArrayClass + { + [PrimaryKey, AutoIncrement] + public int ID { get; set; } + + public byte[] bytes { get; set; } + + public void AssertEquals(ByteArrayClass other) + { + Assert.AreEqual(other.ID, ID); + if (other.bytes == null || bytes == null) + { + Assert.IsNull(other.bytes); + Assert.IsNull(bytes); + } + else + { + Assert.AreEqual(other.bytes.Length, bytes.Length); + for (int i = 0; i < bytes.Length; i++) + { + Assert.AreEqual(other.bytes[i], bytes[i]); + } + } + } + } + + [Test] + [Description("Create objects with various byte arrays and check they can be stored and retrieved correctly")] + public void ByteArrays() + { + //Byte Arrays for comparisson + ByteArrayClass[] byteArrays = + { + new ByteArrayClass + { + bytes = new byte[] {1, 2, 3, 4, 250, 252, 253, 254, 255} + }, //Range check + new ByteArrayClass + { + bytes = new byte[] {0} + }, //null bytes need to be handled correctly + new ByteArrayClass + { + bytes = new byte[] {0, 0} + }, + new ByteArrayClass + { + bytes = new byte[] {0, 1, 0} + }, + new ByteArrayClass + { + bytes = new byte[] {1, 0, 1} + }, + new ByteArrayClass + { + bytes = new byte[] {} + }, //Empty byte array should stay empty (and not become null) + new ByteArrayClass + { + bytes = null + } //Null should be supported + }; + + var database = new SQLiteConnection(_sqlite3Platform, TestPath.GetTempFileName()); + database.CreateTable(); + + //Insert all of the ByteArrayClass + foreach (ByteArrayClass b in byteArrays) + { + database.Insert(b); + } + + //Get them back out + ByteArrayClass[] fetchedByteArrays = database.Table().OrderBy(x => x.ID).ToArray(); + + Assert.AreEqual(fetchedByteArrays.Length, byteArrays.Length); + //Check they are the same + for (int i = 0; i < byteArrays.Length; i++) + { + byteArrays[i].AssertEquals(fetchedByteArrays[i]); + } + } + + [Test] + [Description("Uses a byte array to find a record")] + public void ByteArrayWhere() + { + //Byte Arrays for comparisson + ByteArrayClass[] byteArrays = new ByteArrayClass[] { + new ByteArrayClass() { bytes = new byte[] { 1, 2, 3, 4, 250, 252, 253, 254, 255 } }, //Range check + new ByteArrayClass() { bytes = new byte[] { 0 } }, //null bytes need to be handled correctly + new ByteArrayClass() { bytes = new byte[] { 0, 0 } }, + new ByteArrayClass() { bytes = new byte[] { 0, 1, 0 } }, + new ByteArrayClass() { bytes = new byte[] { 1, 0, 1 } }, + new ByteArrayClass() { bytes = new byte[] { } }, //Empty byte array should stay empty (and not become null) + new ByteArrayClass() { bytes = null } //Null should be supported + }; + + var database = new SQLiteConnection(_sqlite3Platform, TestPath.GetTempFileName()); + database.CreateTable(); + + byte[] criterion = new byte[] { 1, 0, 1 }; + + //Insert all of the ByteArrayClass + int id = 0; + foreach (ByteArrayClass b in byteArrays) + { + database.Insert(b); + if (b.bytes != null && criterion.SequenceEqual(b.bytes)) + id = b.ID; + } + Assert.AreNotEqual(0, id, "An ID wasn't set"); + + //Get it back out + ByteArrayClass fetchedByteArray = database.Table().Where(x => x.bytes == criterion).First(); + Assert.IsNotNull(fetchedByteArray); + //Check they are the same + Assert.AreEqual(id, fetchedByteArray.ID); + } + + [Test] + [Description("Uses a null byte array to find a record")] + public void ByteArrayWhereNull() + { + //Byte Arrays for comparisson + ByteArrayClass[] byteArrays = new ByteArrayClass[] { + new ByteArrayClass() { bytes = new byte[] { 1, 2, 3, 4, 250, 252, 253, 254, 255 } }, //Range check + new ByteArrayClass() { bytes = new byte[] { 0 } }, //null bytes need to be handled correctly + new ByteArrayClass() { bytes = new byte[] { 0, 0 } }, + new ByteArrayClass() { bytes = new byte[] { 0, 1, 0 } }, + new ByteArrayClass() { bytes = new byte[] { 1, 0, 1 } }, + new ByteArrayClass() { bytes = new byte[] { } }, //Empty byte array should stay empty (and not become null) + new ByteArrayClass() { bytes = null } //Null should be supported + }; + + var database = new SQLiteConnection(_sqlite3Platform, TestPath.GetTempFileName()); + database.CreateTable(); + + byte[] criterion = null; + + //Insert all of the ByteArrayClass + int id = 0; + foreach (ByteArrayClass b in byteArrays) + { + database.Insert(b); + if (b.bytes == null) + id = b.ID; + } + Assert.AreNotEqual(0, id, "An ID wasn't set"); + + //Get it back out + ByteArrayClass fetchedByteArray = database.Table().Where(x => x.bytes == criterion).First(); + + Assert.IsNotNull(fetchedByteArray); + //Check they are the same + Assert.AreEqual(id, fetchedByteArray.ID); + } + + [Test] + [Description("Create A large byte array and check it can be stored and retrieved correctly")] + public void LargeByteArray() + { + const int byteArraySize = 1024*1024; + var bytes = new byte[byteArraySize]; + for (int i = 0; i < byteArraySize; i++) + { + bytes[i] = (byte) (i%256); + } + + var byteArray = new ByteArrayClass + { + bytes = bytes + }; + + var database = new SQLiteConnection(_sqlite3Platform, TestPath.GetTempFileName()); + database.CreateTable(); + + //Insert the ByteArrayClass + database.Insert(byteArray); + + //Get it back out + ByteArrayClass[] fetchedByteArrays = database.Table().ToArray(); + + Assert.AreEqual(fetchedByteArrays.Length, 1); + + //Check they are the same + byteArray.AssertEquals(fetchedByteArrays[0]); + } + } +} \ No newline at end of file diff --git a/tests/CollateTest.cs b/tests/CollateTest.cs index 6497b5ab8..3fbffd509 100644 --- a/tests/CollateTest.cs +++ b/tests/CollateTest.cs @@ -1,23 +1,24 @@ using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SQLite; +using NUnit.Framework; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; #else -using NUnit.Framework; +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -using System.Diagnostics; - -namespace SQLite.Tests -{ +namespace SQLite.Net.Tests +{ [TestFixture] public class CollateTest { @@ -25,67 +26,68 @@ public class TestObj { [AutoIncrement, PrimaryKey] public int Id { get; set; } - - public string CollateDefault { get; set; } - - [Collation("BINARY")] - public string CollateBinary { get; set; } - - [Collation("RTRIM")] - public string CollateRTrim { get; set; } - - [Collation("NOCASE")] - public string CollateNoCase { get; set; } - public override string ToString () + public string CollateDefault { get; set; } + + [Collation("BINARY")] + public string CollateBinary { get; set; } + + [Collation("RTRIM")] + public string CollateRTrim { get; set; } + + [Collation("NOCASE")] + public string CollateNoCase { get; set; } + + public override string ToString() { - return string.Format("[TestObj: Id={0}]", Id); + return string.Format("[TestObj: Id={0}]", Id); } } - + public class TestDb : SQLiteConnection { - public TestDb(String path) - : base(path) + public TestDb(ISQLitePlatform sqlitePlatform, String path) + : base(sqlitePlatform, path) { - Trace = true; - CreateTable(); + TraceListener = DebugTraceListener.Instance; + CreateTable(); } } - + [Test] public void Collate() { - var obj = new TestObj() { - CollateDefault = "Alpha ", - CollateBinary = "Alpha ", - CollateRTrim = "Alpha ", - CollateNoCase = "Alpha ", - }; - - var db = new TestDb(TestPath.GetTempFileName()); - - db.Insert(obj); - - Assert.AreEqual(1, (from o in db.Table() where o.CollateDefault == "Alpha " select o).Count()); - Assert.AreEqual(0, (from o in db.Table() where o.CollateDefault == "ALPHA " select o).Count()); - Assert.AreEqual(0, (from o in db.Table() where o.CollateDefault == "Alpha" select o).Count()); - Assert.AreEqual(0, (from o in db.Table() where o.CollateDefault == "ALPHA" select o).Count()); - - Assert.AreEqual(1, (from o in db.Table() where o.CollateBinary == "Alpha " select o).Count()); - Assert.AreEqual(0, (from o in db.Table() where o.CollateBinary == "ALPHA " select o).Count()); - Assert.AreEqual(0, (from o in db.Table() where o.CollateBinary == "Alpha" select o).Count()); - Assert.AreEqual(0, (from o in db.Table() where o.CollateBinary == "ALPHA" select o).Count()); - - Assert.AreEqual(1, (from o in db.Table() where o.CollateRTrim == "Alpha " select o).Count()); - Assert.AreEqual(0, (from o in db.Table() where o.CollateRTrim == "ALPHA " select o).Count()); - Assert.AreEqual(1, (from o in db.Table() where o.CollateRTrim == "Alpha" select o).Count()); - Assert.AreEqual(0, (from o in db.Table() where o.CollateRTrim == "ALPHA" select o).Count()); - - Assert.AreEqual(1, (from o in db.Table() where o.CollateNoCase == "Alpha " select o).Count()); - Assert.AreEqual(1, (from o in db.Table() where o.CollateNoCase == "ALPHA " select o).Count()); - Assert.AreEqual(0, (from o in db.Table() where o.CollateNoCase == "Alpha" select o).Count()); - Assert.AreEqual(0, (from o in db.Table() where o.CollateNoCase == "ALPHA" select o).Count()); + var obj = new TestObj + { + CollateDefault = "Alpha ", + CollateBinary = "Alpha ", + CollateRTrim = "Alpha ", + CollateNoCase = "Alpha ", + }; + + var db = new TestDb(new SQLitePlatformTest(), TestPath.GetTempFileName()); + + db.Insert(obj); + + Assert.AreEqual(1, (from o in db.Table() where o.CollateDefault == "Alpha " select o).Count()); + Assert.AreEqual(0, (from o in db.Table() where o.CollateDefault == "ALPHA " select o).Count()); + Assert.AreEqual(0, (from o in db.Table() where o.CollateDefault == "Alpha" select o).Count()); + Assert.AreEqual(0, (from o in db.Table() where o.CollateDefault == "ALPHA" select o).Count()); + + Assert.AreEqual(1, (from o in db.Table() where o.CollateBinary == "Alpha " select o).Count()); + Assert.AreEqual(0, (from o in db.Table() where o.CollateBinary == "ALPHA " select o).Count()); + Assert.AreEqual(0, (from o in db.Table() where o.CollateBinary == "Alpha" select o).Count()); + Assert.AreEqual(0, (from o in db.Table() where o.CollateBinary == "ALPHA" select o).Count()); + + Assert.AreEqual(1, (from o in db.Table() where o.CollateRTrim == "Alpha " select o).Count()); + Assert.AreEqual(0, (from o in db.Table() where o.CollateRTrim == "ALPHA " select o).Count()); + Assert.AreEqual(1, (from o in db.Table() where o.CollateRTrim == "Alpha" select o).Count()); + Assert.AreEqual(0, (from o in db.Table() where o.CollateRTrim == "ALPHA" select o).Count()); + + Assert.AreEqual(1, (from o in db.Table() where o.CollateNoCase == "Alpha " select o).Count()); + Assert.AreEqual(1, (from o in db.Table() where o.CollateNoCase == "ALPHA " select o).Count()); + Assert.AreEqual(0, (from o in db.Table() where o.CollateNoCase == "Alpha" select o).Count()); + Assert.AreEqual(0, (from o in db.Table() where o.CollateNoCase == "ALPHA" select o).Count()); } } -} +} \ No newline at end of file diff --git a/tests/ConnectionTrackingTest.cs b/tests/ConnectionTrackingTest.cs index 6ba0a2b05..fab6fc0a9 100644 --- a/tests/ConnectionTrackingTest.cs +++ b/tests/ConnectionTrackingTest.cs @@ -1,79 +1,108 @@ - -using System; -using System.IO; -using System.Collections.Generic; using System.Linq; -using System.Text; -using SQLite; +using NUnit.Framework; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; -#if NETFX_CORE -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SetUp = Microsoft.VisualStudio.TestTools.UnitTesting.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute; +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; #else -using NUnit.Framework; +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif - -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class ConnectionTrackingTest - { - public class Product - { - [AutoIncrement, PrimaryKey] - public int Id { get; set; } - public string Name { get; set; } - public decimal Price { get; set; } + [NUnit.Framework.Ignore("This test class/file was not included in the original project and is broken")] + [TestFixture] + public class ConnectionTrackingTest + { + public class Product + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public string Name { get; set; } + public decimal Price { get; set; } + + public TestDb Connection { get; private set; } + + public OrderLine[] GetOrderLines() + { + return Connection.Table().Where(o => o.ProductId == Id).ToArray(); + } + } + + public class OrderLine + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public int ProductId { get; set; } + public int Quantity { get; set; } + public decimal UnitPrice { get; set; } + + public TestDb Connection { get; private set; } + } - public TestDb Connection { get; private set; } + public class TestDb : SQLiteConnection + { + public TestDb(ISQLitePlatform sqlitePlatform) + : base(sqlitePlatform, TestPath.GetTempFileName()) + { + CreateTable(); + CreateTable(); + TraceListener = DebugTraceListener.Instance; + } + } - public OrderLine[] GetOrderLines () - { - return Connection.Table ().Where (o => o.ProductId == Id).ToArray (); - } - } - public class OrderLine - { - [AutoIncrement, PrimaryKey] - public int Id { get; set; } - public int ProductId { get; set; } - public int Quantity { get; set; } - public decimal UnitPrice { get; set; } + [Test] + public void CreateThem() + { + var db = new TestDb(new SQLitePlatformTest()); - public TestDb Connection { get; private set; } - } + var foo = new Product + { + Name = "Foo", + Price = 10.0m + }; + var bar = new Product + { + Name = "Bar", + Price = 0.10m + }; + db.Insert(foo); + db.Insert(bar); + db.Insert(new OrderLine + { + ProductId = foo.Id, + Quantity = 6, + UnitPrice = 10.01m + }); + db.Insert(new OrderLine + { + ProductId = foo.Id, + Quantity = 3, + UnitPrice = 0.02m + }); + db.Insert(new OrderLine + { + ProductId = bar.Id, + Quantity = 9, + UnitPrice = 100.01m + }); - public class TestDb : SQLiteConnection - { - public TestDb () : base(TestPath.GetTempFileName ()) - { - CreateTable (); - CreateTable (); - Trace = true; - } - } + OrderLine[] lines = foo.GetOrderLines(); - [Test] - public void CreateThem () - { - var db = new TestDb (); - - var foo = new Product { Name = "Foo", Price = 10.0m }; - var bar = new Product { Name = "Bar", Price = 0.10m }; - db.Insert (foo); - db.Insert (bar); - db.Insert (new OrderLine { ProductId = foo.Id, Quantity = 6, UnitPrice = 10.01m }); - db.Insert (new OrderLine { ProductId = foo.Id, Quantity = 3, UnitPrice = 0.02m }); - db.Insert (new OrderLine { ProductId = bar.Id, Quantity = 9, UnitPrice = 100.01m }); - - var lines = foo.GetOrderLines (); - - Assert.AreEqual (lines.Length, 2, "Has 2 order lines"); - Assert.AreEqual (foo.Connection, db, "foo.Connection was set"); - Assert.AreEqual (lines[0].Connection, db, "lines[0].Connection was set"); - } - } -} + Assert.AreEqual(lines.Length, 2, "Has 2 order lines"); + Assert.AreEqual(foo.Connection, db, "foo.Connection was set"); + Assert.AreEqual(lines[0].Connection, db, "lines[0].Connection was set"); + } + } +} \ No newline at end of file diff --git a/tests/ContainsTest.cs b/tests/ContainsTest.cs index e16c611dd..d3ce9298a 100644 --- a/tests/ContainsTest.cs +++ b/tests/ContainsTest.cs @@ -1,23 +1,23 @@ -using System; -using System.IO; using System.Collections.Generic; using System.Linq; -using System.Text; -using SQLite; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; -#endif +using SQLite.Net.Attributes; +using SQLite.Net.Interop; -using System.Diagnostics; +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; +#endif -namespace SQLite.Tests -{ +namespace SQLite.Net.Tests +{ [TestFixture] public class ContainsTest { @@ -25,75 +25,77 @@ public class TestObj { [AutoIncrement, PrimaryKey] public int Id { get; set; } - - public string Name { get; set; } - - public override string ToString () + + public string Name { get; set; } + + public override string ToString() { - return string.Format("[TestObj: Id={0}, Name={1}]", Id, Name); + return string.Format("[TestObj: Id={0}, Name={1}]", Id, Name); } } - + public class TestDb : SQLiteConnection { - public TestDb(String path) - : base(path) + public TestDb(ISQLitePlatform sqlitePlatform, string path) + : base(sqlitePlatform, path) { - CreateTable(); + CreateTable(); } } - + [Test] public void ContainsConstantData() { - int n = 20; - var cq =from i in Enumerable.Range(1, n) - select new TestObj() { - Name = i.ToString() - }; - - var db = new TestDb(TestPath.GetTempFileName()); - - db.InsertAll(cq); - - db.Trace = true; - - var tensq = new string[] { "0", "10", "20" }; - var tens = (from o in db.Table() where tensq.Contains(o.Name) select o).ToList(); - Assert.AreEqual(2, tens.Count); - - var moreq = new string[] { "0", "x", "99", "10", "20", "234324" }; - var more = (from o in db.Table() where moreq.Contains(o.Name) select o).ToList(); - Assert.AreEqual(2, more.Count); + int n = 20; + IEnumerable cq = from i in Enumerable.Range(1, n) + select new TestObj + { + Name = i.ToString() + }; + + var db = new TestDb(new SQLitePlatformTest(), TestPath.GetTempFileName()); + + db.InsertAll(cq); + + db.TraceListener = DebugTraceListener.Instance; + + var tensq = new[] {"0", "10", "20"}; + List tens = (from o in db.Table() where tensq.Contains(o.Name) select o).ToList(); + Assert.AreEqual(2, tens.Count); + + var moreq = new[] {"0", "x", "99", "10", "20", "234324"}; + List more = (from o in db.Table() where moreq.Contains(o.Name) select o).ToList(); + Assert.AreEqual(2, more.Count); } - - [Test] + + [Test] public void ContainsQueriedData() { - int n = 20; - var cq =from i in Enumerable.Range(1, n) - select new TestObj() { - Name = i.ToString() - }; - - var db = new TestDb(TestPath.GetTempFileName()); - - db.InsertAll(cq); - - db.Trace = true; - - var tensq = new string[] { "0", "10", "20" }; - var tens = (from o in db.Table() where tensq.Contains(o.Name) select o).ToList(); - Assert.AreEqual(2, tens.Count); - - var moreq = new string[] { "0", "x", "99", "10", "20", "234324" }; - var more = (from o in db.Table() where moreq.Contains(o.Name) select o).ToList(); - Assert.AreEqual(2, more.Count); - - // https://github.com/praeclarum/sqlite-net/issues/28 - var moreq2 = moreq.ToList (); - var more2 = (from o in db.Table() where moreq2.Contains(o.Name) select o).ToList(); - Assert.AreEqual(2, more2.Count); + int n = 20; + IEnumerable cq = from i in Enumerable.Range(1, n) + select new TestObj + { + Name = i.ToString() + }; + + var db = new TestDb(new SQLitePlatformTest(), TestPath.GetTempFileName()); + + db.InsertAll(cq); + + db.TraceListener = DebugTraceListener.Instance; + + var tensq = new[] {"0", "10", "20"}; + List tens = (from o in db.Table() where tensq.Contains(o.Name) select o).ToList(); + Assert.AreEqual(2, tens.Count); + + var moreq = new[] {"0", "x", "99", "10", "20", "234324"}; + List more = (from o in db.Table() where moreq.Contains(o.Name) select o).ToList(); + Assert.AreEqual(2, more.Count); + + // https://github.com/praeclarum/SQLite.Net/issues/28 + List moreq2 = moreq.ToList(); + List more2 = (from o in db.Table() where moreq2.Contains(o.Name) select o).ToList(); + Assert.AreEqual(2, more2.Count); } } -} +} \ No newline at end of file diff --git a/tests/CreateTableImplicitTest.cs b/tests/CreateTableImplicitTest.cs index a1095dd6f..5ef716755 100644 --- a/tests/CreateTableImplicitTest.cs +++ b/tests/CreateTableImplicitTest.cs @@ -1,34 +1,25 @@ -using System; -using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; -#endif +using SQLite.Net.Attributes; +using SQLite.Net.Interop; -namespace SQLite.Tests +namespace SQLite.Net.Tests { [TestFixture] public class CreateTableImplicitTest { - - class NoAttributes + private class NoAttributes { public int Id { get; set; } public string AColumn { get; set; } public int IndexedId { get; set; } } - class PkAttribute + private class PkAttribute { [PrimaryKey] public int Id { get; set; } + public string AColumn { get; set; } public int IndexedId { get; set; } } @@ -37,7 +28,12 @@ private void CheckPK(TestDb db) { for (int i = 1; i <= 10; i++) { - var na = new NoAttributes { Id = i, AColumn = i.ToString(), IndexedId = 0 }; + var na = new NoAttributes + { + Id = i, + AColumn = i.ToString(), + IndexedId = 0 + }; db.Insert(na); } var item = db.Get(2); @@ -45,50 +41,30 @@ private void CheckPK(TestDb db) Assert.AreEqual(2, item.Id); } - [Test] - public void WithoutImplicitMapping () - { - var db = new TestDb (); - - db.CreateTable(); - - var mapping = db.GetMapping(); - - Assert.IsNull (mapping.PK); - - var column = mapping.Columns[2]; - Assert.AreEqual("IndexedId", column.Name); - Assert.IsFalse(column.Indices.Any()); - - Assert.Throws(typeof(AssertionException), () => CheckPK(db)); - } [Test] - public void ImplicitPK() + public void ImplicitAutoInc() { var db = new TestDb(); - db.CreateTable(CreateFlags.ImplicitPK); + db.CreateTable(CreateFlags.AutoIncPK); - var mapping = db.GetMapping(); + TableMapping mapping = db.GetMapping(); Assert.IsNotNull(mapping.PK); Assert.AreEqual("Id", mapping.PK.Name); Assert.IsTrue(mapping.PK.IsPK); - Assert.IsFalse(mapping.PK.IsAutoInc); - - CheckPK(db); + Assert.IsTrue(mapping.PK.IsAutoInc); } - [Test] - public void ImplicitAutoInc() + public void ImplicitAutoIncAsPassedInTypes() { var db = new TestDb(); - db.CreateTable(CreateFlags.AutoIncPK); + db.CreateTable(typeof (PkAttribute), CreateFlags.AutoIncPK); - var mapping = db.GetMapping(); + TableMapping mapping = db.GetMapping(); Assert.IsNotNull(mapping.PK); Assert.AreEqual("Id", mapping.PK.Name); @@ -103,20 +79,37 @@ public void ImplicitIndex() db.CreateTable(CreateFlags.ImplicitIndex); - var mapping = db.GetMapping(); - var column = mapping.Columns[2]; + TableMapping mapping = db.GetMapping(); + TableMapping.Column column = mapping.Columns[2]; Assert.AreEqual("IndexedId", column.Name); Assert.IsTrue(column.Indices.Any()); } + [Test] + public void ImplicitPK() + { + var db = new TestDb(); + + db.CreateTable(CreateFlags.ImplicitPK); + + TableMapping mapping = db.GetMapping(); + + Assert.IsNotNull(mapping.PK); + Assert.AreEqual("Id", mapping.PK.Name); + Assert.IsTrue(mapping.PK.IsPK); + Assert.IsFalse(mapping.PK.IsAutoInc); + + CheckPK(db); + } + [Test] public void ImplicitPKAutoInc() { var db = new TestDb(); - db.CreateTable(typeof(NoAttributes), CreateFlags.ImplicitPK | CreateFlags.AutoIncPK); + db.CreateTable(typeof (NoAttributes), CreateFlags.ImplicitPK | CreateFlags.AutoIncPK); - var mapping = db.GetMapping(); + TableMapping mapping = db.GetMapping(); Assert.IsNotNull(mapping.PK); Assert.AreEqual("Id", mapping.PK.Name); @@ -125,13 +118,13 @@ public void ImplicitPKAutoInc() } [Test] - public void ImplicitAutoIncAsPassedInTypes() + public void ImplicitPKAutoIncAsPassedInTypes() { var db = new TestDb(); - db.CreateTable(typeof(PkAttribute), CreateFlags.AutoIncPK); + db.CreateTable(typeof (NoAttributes), CreateFlags.ImplicitPK | CreateFlags.AutoIncPK); - var mapping = db.GetMapping(); + TableMapping mapping = db.GetMapping(); Assert.IsNotNull(mapping.PK); Assert.AreEqual("Id", mapping.PK.Name); @@ -144,9 +137,9 @@ public void ImplicitPkAsPassedInTypes() { var db = new TestDb(); - db.CreateTable(typeof(NoAttributes), CreateFlags.ImplicitPK); + db.CreateTable(typeof (NoAttributes), CreateFlags.ImplicitPK); - var mapping = db.GetMapping(); + TableMapping mapping = db.GetMapping(); Assert.IsNotNull(mapping.PK); Assert.AreEqual("Id", mapping.PK.Name); @@ -155,19 +148,21 @@ public void ImplicitPkAsPassedInTypes() } [Test] - public void ImplicitPKAutoIncAsPassedInTypes() + public void WithoutImplicitMapping() { var db = new TestDb(); - db.CreateTable(typeof(NoAttributes), CreateFlags.ImplicitPK | CreateFlags.AutoIncPK); + db.CreateTable(); - var mapping = db.GetMapping(); + TableMapping mapping = db.GetMapping(); - Assert.IsNotNull(mapping.PK); - Assert.AreEqual("Id", mapping.PK.Name); - Assert.IsTrue(mapping.PK.IsPK); - Assert.IsTrue(mapping.PK.IsAutoInc); + Assert.IsNull(mapping.PK); + + TableMapping.Column column = mapping.Columns[2]; + Assert.AreEqual("IndexedId", column.Name); + Assert.IsFalse(column.Indices.Any()); + + Assert.Throws(typeof (AssertionException), () => CheckPK(db)); } } -} - +} \ No newline at end of file diff --git a/tests/CreateTableTest.cs b/tests/CreateTableTest.cs index 8cee5d78e..dbf33b7c2 100644 --- a/tests/CreateTableTest.cs +++ b/tests/CreateTableTest.cs @@ -1,99 +1,94 @@ -using System; using System.Linq; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; -#endif - +using SQLite.Net.Attributes; -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class CreateTableTest - { - [Test] - public void CreateThem () - { - var db = new TestDb (); - - db.CreateTable (); - db.CreateTable (); - db.CreateTable (); - db.CreateTable (); - - VerifyCreations(db); - } + [TestFixture] + public class CreateTableTest + { + private static void VerifyCreations(TestDb db) + { + TableMapping orderLine = db.GetMapping(typeof (OrderLine)); + Assert.AreEqual(6, orderLine.Columns.Length); - [Test] - public void CreateAsPassedInTypes () + var l = new OrderLine + { + Status = OrderLineStatus.Shipped + }; + db.Insert(l); + OrderLine lo = db.Table().First(x => x.Status == OrderLineStatus.Shipped); + Assert.AreEqual(lo.Id, l.Id); + } + + private class Issue115_MyObject + { + [PrimaryKey] + public string UniqueId { get; set; } + + public byte OtherValue { get; set; } + } + + [Test] + public void CreateAsPassedInTypes() { var db = new TestDb(); - db.CreateTable(typeof(Product)); - db.CreateTable(typeof(Order)); - db.CreateTable(typeof(OrderLine)); - db.CreateTable(typeof(OrderHistory)); + db.CreateTable(typeof (Product)); + db.CreateTable(typeof (Order)); + db.CreateTable(typeof (OrderLine)); + db.CreateTable(typeof (OrderHistory)); VerifyCreations(db); } - [Test] - public void CreateTwice () - { - var db = new TestDb (); - - db.CreateTable (); - db.CreateTable (); - db.CreateTable (); - db.CreateTable (); - db.CreateTable (); - - VerifyCreations(db); - } - - private static void VerifyCreations(TestDb db) + [Test] + public void CreateThem() { - var orderLine = db.GetMapping(typeof(OrderLine)); - Assert.AreEqual(6, orderLine.Columns.Length); + var db = new TestDb(); - var l = new OrderLine() - { - Status = OrderLineStatus.Shipped - }; - db.Insert(l); - var lo = db.Table().First(x => x.Status == OrderLineStatus.Shipped); - Assert.AreEqual(lo.Id, l.Id); + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + + VerifyCreations(db); } - class Issue115_MyObject - { - [PrimaryKey] - public string UniqueId { get; set; } - public byte OtherValue { get; set; } - } + [Test] + public void CreateTwice() + { + var db = new TestDb(); - [Test] - public void Issue115_MissingPrimaryKey () - { - using (var conn = new TestDb ()) { + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + + VerifyCreations(db); + } - conn.CreateTable (); - conn.InsertAll (from i in Enumerable.Range (0, 10) select new Issue115_MyObject { - UniqueId = i.ToString (), - OtherValue = (byte)(i * 10), - }); + [Test] + public void Issue115_MissingPrimaryKey() + { + using (var conn = new TestDb()) + { + conn.CreateTable(); + conn.InsertAll(from i in Enumerable.Range(0, 10) + select new Issue115_MyObject + { + UniqueId = i.ToString(), + OtherValue = (byte) (i*10), + }); - var query = conn.Table (); - foreach (var itm in query) { - itm.OtherValue++; - Assert.AreEqual (1, conn.Update (itm, typeof(Issue115_MyObject))); - } - } - } + TableQuery query = conn.Table(); + foreach (Issue115_MyObject itm in query) + { + itm.OtherValue++; + Assert.AreEqual(1, conn.Update(itm, typeof (Issue115_MyObject))); + } + } + } } -} +} \ No newline at end of file diff --git a/tests/DateTimeOffsetTest.cs b/tests/DateTimeOffsetTest.cs new file mode 100644 index 000000000..0250967e9 --- /dev/null +++ b/tests/DateTimeOffsetTest.cs @@ -0,0 +1,87 @@ +using System; +using SQLite.Net.Async; +using SQLite.Net.Attributes; +using NUnit.Framework; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; +#endif + + +namespace SQLite.Net.Tests +{ + [TestFixture] + public class DateTimeOffsetTest + { + class TestObj + { + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + + public string Name { get; set; } + public DateTimeOffset ModifiedTime { get; set; } + } + + [Test] + public void AsTicks () + { + var db = new TestDb (); + TestDateTimeOffset (db); + } + + [Test] + public void AsyncAsTicks () + { + var sqLiteConnectionPool = new SQLiteConnectionPool(new SQLitePlatformTest()); + var sqLiteConnectionString = new SQLiteConnectionString(TestPath.GetTempFileName(), false); + var db = new SQLiteAsyncConnection(() => sqLiteConnectionPool.GetConnection(sqLiteConnectionString)); + TestAsyncDateTimeOffset (db); + } + + void TestAsyncDateTimeOffset (SQLiteAsyncConnection db) + { + db.CreateTableAsync ().Wait (); + + TestObj o, o2; + + // + // Ticks + // + o = new TestObj { + ModifiedTime = new DateTimeOffset (2012, 1, 14, 3, 2, 1, TimeSpan.Zero), + }; + db.InsertAsync (o).Wait (); + o2 = db.GetAsync (o.Id).Result; + Assert.AreEqual (o.ModifiedTime, o2.ModifiedTime); + } + + void TestDateTimeOffset (TestDb db) + { + db.CreateTable (); + + TestObj o, o2; + + // + // Ticks + // + o = new TestObj { + ModifiedTime = new DateTimeOffset (2012, 1, 14, 3, 2, 1, TimeSpan.Zero), + }; + db.Insert (o); + o2 = db.Get (o.Id); + Assert.AreEqual (o.ModifiedTime, o2.ModifiedTime); + } + + } +} + diff --git a/tests/DateTimeTest.cs b/tests/DateTimeTest.cs index 253c10f5a..217d13fe0 100644 --- a/tests/DateTimeTest.cs +++ b/tests/DateTimeTest.cs @@ -1,90 +1,105 @@ using System; +using System.Threading.Tasks; +using NUnit.Framework; +using SQLite.Net.Async; +using SQLite.Net.Attributes; -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; #else -using NUnit.Framework; +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -namespace SQLite.Tests -{ - [TestFixture] - public class DateTimeTest - { - class TestObj - { - [PrimaryKey, AutoIncrement] - public int Id { get; set; } - public string Name { get; set; } - public DateTime ModifiedTime { get; set; } - } +namespace SQLite.Net.Tests +{ + [TestFixture] + public class DateTimeTest + { + private class TestObj + { + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + public string Name { get; set; } + public DateTime ModifiedTime { get; set; } + } - [Test] - public void AsTicks () - { - var db = new TestDb (storeDateTimeAsTicks: true); - TestDateTime (db); - } - [Test] - public void AsStrings () - { - var db = new TestDb (storeDateTimeAsTicks: false); - TestDateTime (db); - } + private async Task TestAsyncDateTime(SQLiteAsyncConnection db) + { + await db.CreateTableAsync(); - [Test] - public void AsyncAsTicks () - { - var db = new SQLiteAsyncConnection (TestPath.GetTempFileName (), true); - TestAsyncDateTime (db); - } + TestObj o, o2; - [Test] - public void AsyncAsString () - { - var db = new SQLiteAsyncConnection (TestPath.GetTempFileName (), false); - TestAsyncDateTime (db); - } + // + // Ticks + // + o = new TestObj + { + ModifiedTime = new DateTime(2012, 1, 14, 3, 2, 1), + }; + await db.InsertAsync(o); + o2 = await db.GetAsync(o.Id); + Assert.AreEqual(o.ModifiedTime, o2.ModifiedTime); + } - void TestAsyncDateTime (SQLiteAsyncConnection db) - { - db.CreateTableAsync ().Wait (); + private void TestDateTime(TestDb db) + { + db.CreateTable(); - TestObj o, o2; + TestObj o, o2; - // - // Ticks - // - o = new TestObj { - ModifiedTime = new DateTime (2012, 1, 14, 3, 2, 1), - }; - db.InsertAsync (o).Wait (); - o2 = db.GetAsync (o.Id).Result; - Assert.AreEqual (o.ModifiedTime, o2.ModifiedTime); - } + // + // Ticks + // + o = new TestObj + { + ModifiedTime = new DateTime(2012, 1, 14, 3, 2, 1), + }; + db.Insert(o); + o2 = db.Get(o.Id); + Assert.AreEqual(o.ModifiedTime, o2.ModifiedTime); + } - void TestDateTime (TestDb db) - { - db.CreateTable (); + [Test] + public void AsStrings() + { + var db = new TestDb(storeDateTimeAsTicks: false); + TestDateTime(db); + } - TestObj o, o2; + [Test] + public void AsTicks() + { + var db = new TestDb(true); + TestDateTime(db); + } - // - // Ticks - // - o = new TestObj { - ModifiedTime = new DateTime (2012, 1, 14, 3, 2, 1), - }; - db.Insert (o); - o2 = db.Get (o.Id); - Assert.AreEqual (o.ModifiedTime, o2.ModifiedTime); - } - } -} + [Test] + public async Task AsyncAsString() + { + var sqLiteConnectionPool = new SQLiteConnectionPool(new SQLitePlatformTest()); + var sqLiteConnectionString = new SQLiteConnectionString(TestPath.GetTempFileName(), false); + var db = new SQLiteAsyncConnection(() => sqLiteConnectionPool.GetConnection(sqLiteConnectionString)); + await TestAsyncDateTime(db); + } + [Test] + public async Task AsyncAsTicks() + { + var sqLiteConnectionPool = new SQLiteConnectionPool(new SQLitePlatformTest()); + var sqLiteConnectionString = new SQLiteConnectionString(TestPath.GetTempFileName(), true); + var db = new SQLiteAsyncConnection(() => sqLiteConnectionPool.GetConnection(sqLiteConnectionString)); + await TestAsyncDateTime(db); + } + } +} \ No newline at end of file diff --git a/tests/DefaulAttributeTest.cs b/tests/DefaulAttributeTest.cs new file mode 100644 index 000000000..fdb880873 --- /dev/null +++ b/tests/DefaulAttributeTest.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using NUnit.Framework; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; +#endif + +namespace SQLite.Net.Tests +{ + [TestFixture] + public class DefaulAttributeTest + { + private class WithDefaultValue + { + + public static int IntVal = 666; + public static decimal DecimalVal = 666.666m; + public static string StringVal = "Working String"; + public static DateTime DateTimegVal = new DateTime(2014, 2, 13); + + public WithDefaultValue() + { + TestInt = IntVal; + TestDateTime = DateTimegVal; + TestDecimal = DecimalVal; + TestString = StringVal; + } + + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + + + [Default] + public int TestInt { get; set; } + + [Default] + public decimal TestDecimal { get; set; } + + [Default] + public DateTime TestDateTime { get; set; } + + [Default] + public string TestString { get; set; } + + } + + [Test] + public void TestColumnValues() + { + using (TestDb db = new TestDb()) + { + db.CreateTable(); + + + string failed = string.Empty; + foreach (var col in db.GetMapping().Columns) + { + if (col.PropertyName == "TestInt" && !col.DefaultValue.Equals(WithDefaultValue.IntVal)) + failed += " , TestInt does not equal " + WithDefaultValue.IntVal; + + if (col.PropertyName == "TestDecimal" && !col.DefaultValue.Equals(WithDefaultValue.DecimalVal)) + failed += "TestDecimal does not equal " + WithDefaultValue.DecimalVal; + + if (col.PropertyName == "TestDateTime" && !col.DefaultValue.Equals(WithDefaultValue.DateTimegVal)) + failed += "TestDateTime does not equal " + WithDefaultValue.DateTimegVal; + + if (col.PropertyName == "TestString" && !col.DefaultValue.Equals(WithDefaultValue.StringVal)) + failed += "TestString does not equal " + WithDefaultValue.StringVal; + } + + Assert.True(string.IsNullOrWhiteSpace(failed), failed); + + } + } + } +} \ No newline at end of file diff --git a/tests/DeleteTest.cs b/tests/DeleteTest.cs index b5ab1614a..7c8ab7117 100644 --- a/tests/DeleteTest.cs +++ b/tests/DeleteTest.cs @@ -1,83 +1,79 @@ -using System; +using System.Collections.Generic; using System.Linq; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; -#endif +using SQLite.Net.Attributes; -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class DeleteTest - { - class TestTable - { - [PrimaryKey, AutoIncrement] - public int Id { get; set; } - public int Datum { get; set; } - } - - const int Count = 100; - - SQLiteConnection CreateDb () - { - var db = new TestDb (); - db.CreateTable (); - var items = from i in Enumerable.Range (0, Count) - select new TestTable { Datum = 1000+i }; - db.InsertAll (items); - Assert.AreEqual (Count, db.Table ().Count ()); - return db; - } - - [Test] - public void DeleteEntityOne () - { - var db = CreateDb (); - - var r = db.Delete (db.Get (1)); - - Assert.AreEqual (1, r); - Assert.AreEqual (Count - 1, db.Table ().Count ()); - } - - [Test] - public void DeletePKOne () - { - var db = CreateDb (); - - var r = db.Delete (1); - - Assert.AreEqual (1, r); - Assert.AreEqual (Count - 1, db.Table ().Count ()); - } - - [Test] - public void DeletePKNone () - { - var db = CreateDb (); - - var r = db.Delete (348597); - - Assert.AreEqual (0, r); - Assert.AreEqual (Count, db.Table ().Count ()); - } - - [Test] - public void DeleteAll () - { - var db = CreateDb (); - - var r = db.DeleteAll (); - - Assert.AreEqual (Count, r); - Assert.AreEqual (0, db.Table ().Count ()); - } - } -} - + [TestFixture] + public class DeleteTest + { + private class TestTable + { + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + + public int Datum { get; set; } + } + + private const int Count = 100; + + private SQLiteConnection CreateDb() + { + var db = new TestDb(); + db.CreateTable(); + IEnumerable items = from i in Enumerable.Range(0, Count) + select new TestTable + { + Datum = 1000 + i + }; + db.InsertAll(items); + Assert.AreEqual(Count, db.Table().Count()); + return db; + } + + [Test] + public void DeleteAll() + { + SQLiteConnection db = CreateDb(); + + int r = db.DeleteAll(); + + Assert.AreEqual(Count, r); + Assert.AreEqual(0, db.Table().Count()); + } + + [Test] + public void DeleteEntityOne() + { + SQLiteConnection db = CreateDb(); + + int r = db.Delete(db.Get(1)); + + Assert.AreEqual(1, r); + Assert.AreEqual(Count - 1, db.Table().Count()); + } + + [Test] + public void DeletePKNone() + { + SQLiteConnection db = CreateDb(); + + int r = db.Delete(348597); + + Assert.AreEqual(0, r); + Assert.AreEqual(Count, db.Table().Count()); + } + + [Test] + public void DeletePKOne() + { + SQLiteConnection db = CreateDb(); + + int r = db.Delete(1); + + Assert.AreEqual(1, r); + Assert.AreEqual(Count - 1, db.Table().Count()); + } + } +} \ No newline at end of file diff --git a/tests/DropTableTest.cs b/tests/DropTableTest.cs index 1124cb9ba..d8fa8b00b 100644 --- a/tests/DropTableTest.cs +++ b/tests/DropTableTest.cs @@ -1,61 +1,62 @@ +using NUnit.Framework; +using SQLite.Net.Attributes; -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SQLite; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; #else -using NUnit.Framework; +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif - -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class DropTableTest - { - public class Product - { - [AutoIncrement, PrimaryKey] - public int Id { get; set; } - public string Name { get; set; } - public decimal Price { get; set; } - } - - public class TestDb : SQLiteConnection - { - public TestDb () : base(TestPath.GetTempFileName ()) - { - Trace = true; - } - } - - [Test] - public void CreateInsertDrop () - { - var db = new TestDb (); - - db.CreateTable (); - - db.Insert (new Product { - Name = "Hello", - Price = 16, - }); - - var n = db.Table ().Count (); - - Assert.AreEqual (1, n); - - db.DropTable (); - - ExceptionAssert.Throws(() => db.Table ().Count ()); - } - } -} + [TestFixture] + public class DropTableTest + { + public class Product + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public string Name { get; set; } + public decimal Price { get; set; } + } + + public class TestDb : SQLiteConnection + { + public TestDb() : base(new SQLitePlatformTest(), TestPath.GetTempFileName()) + { + TraceListener = DebugTraceListener.Instance; + } + } + + [Test] + public void CreateInsertDrop() + { + var db = new TestDb(); + + db.CreateTable(); + + db.Insert(new Product + { + Name = "Hello", + Price = 16, + }); + + int n = db.Table().Count(); + + Assert.AreEqual(1, n); + + db.DropTable(); + + ExceptionAssert.Throws(() => db.Table().Count()); + } + } +} \ No newline at end of file diff --git a/tests/EqualsTest.cs b/tests/EqualsTest.cs index 02210725d..9aaaec738 100644 --- a/tests/EqualsTest.cs +++ b/tests/EqualsTest.cs @@ -1,18 +1,28 @@ using System; +using System.Collections.Generic; using System.Linq; -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; +using SQLite.Net.Attributes; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -namespace SQLite.Tests + +namespace SQLite.Net.Tests { [TestFixture] - class EqualsTest + internal class EqualsTest { public abstract class TestObjBase { @@ -24,12 +34,14 @@ public abstract class TestObjBase public DateTime Date { get; set; } } - public class TestObjString : TestObjBase { } + public class TestObjString : TestObjBase + { + } public class TestDb : SQLiteConnection { public TestDb(String path) - : base(path) + : base(new SQLitePlatformTest(), path) { CreateTable(); } @@ -38,17 +50,18 @@ public TestDb(String path) [Test] public void CanCompareAnyField() { - var n = 20; - var cq =from i in Enumerable.Range(1, n) - select new TestObjString { - Data = Convert.ToString(i), - Date = new DateTime(2013, 1, i) - }; + int n = 20; + IEnumerable cq = from i in Enumerable.Range(1, n) + select new TestObjString + { + Data = Convert.ToString(i), + Date = new DateTime(2013, 1, i) + }; var db = new TestDb(TestPath.GetTempFileName()); db.InsertAll(cq); - var results = db.Table().Where(o => o.Data.Equals("10")); + TableQuery results = db.Table().Where(o => o.Data.Equals("10")); Assert.AreEqual(results.Count(), 1); Assert.AreEqual(results.FirstOrDefault().Data, "10"); @@ -62,4 +75,4 @@ public void CanCompareAnyField() Assert.AreEqual(results.FirstOrDefault().Data, "10"); } } -} +} \ No newline at end of file diff --git a/tests/ExceptionAssert.cs b/tests/ExceptionAssert.cs index b97bea109..8ea5af37a 100644 --- a/tests/ExceptionAssert.cs +++ b/tests/ExceptionAssert.cs @@ -1,33 +1,24 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -#else using NUnit.Framework; -#endif -namespace SQLite.Tests +namespace SQLite.Net.Tests { - public class ExceptionAssert - { - public static T Throws(Action action) where T : Exception - { - try - { - action(); - } - catch (T ex) - { - return ex; - } + public class ExceptionAssert + { + public static T Throws(Action action) where T : Exception + { + try + { + action(); + } + catch (T ex) + { + return ex; + } - Assert.Fail("Expected exception of type {0}.", typeof(T)); + Assert.Fail("Expected exception of type {0}.", typeof (T)); - return null; - } - } -} + return null; + } + } +} \ No newline at end of file diff --git a/tests/ExpressionTests.cs b/tests/ExpressionTests.cs new file mode 100644 index 000000000..81d1b0f41 --- /dev/null +++ b/tests/ExpressionTests.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using NUnit.Framework; +using SQLite.Net.Attributes; + +namespace SQLite.Net.Tests +{ + [TestFixture] + public class ExpressionTests + { + [Table("AGoodTableName")] + private class TestTable + { + [PrimaryKey] + public int Id { get; set; } + + public string Name { get; set; } + } + + + [Test] + public void ToLower() + { + var db = new TestDb(); + + db.CreateTable(); + var testTable = new TestTable() + { + Name = "TEST" + }; + db.Insert(testTable); + + var x = db.Table().Where(t => t.Name.ToLower() == "test"); + + Assert.AreEqual(1, x.Count()); + } + + [Test] + public void ToUpper() + { + var db = new TestDb(); + + db.CreateTable(); + var testTable = new TestTable() + { + Name = "test" + }; + db.Insert(testTable); + + var x = db.Table().Where(t => t.Name.ToUpper() == "TEST"); + + Assert.AreEqual(1, x.Count()); + } + } +} \ No newline at end of file diff --git a/tests/GuidTests.cs b/tests/GuidTests.cs index 87b58c5de..d1bb251af 100644 --- a/tests/GuidTests.cs +++ b/tests/GuidTests.cs @@ -1,59 +1,78 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Text; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -namespace SQLite.Tests { +namespace SQLite.Net.Tests +{ [TestFixture] - public class GuidTests { - public class TestObj { + public class GuidTests + { + public class TestObj + { [PrimaryKey] public Guid Id { get; set; } + public String Text { get; set; } - public override string ToString() { + public override string ToString() + { return string.Format("[TestObj: Id={0}, Text={1}]", Id, Text); } - } - public class TestDb : SQLiteConnection { + public class TestDb : SQLiteConnection + { public TestDb(String path) - : base(path) { + : base(new SQLitePlatformTest(), path) + { CreateTable(); } } [Test] - public void ShouldPersistAndReadGuid() { - var db = new TestDb(TestPath.GetTempFileName()); + public void AutoGuid_EmptyGuid() + { + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); + db.CreateTable(CreateFlags.AutoIncPK); - var obj1 = new TestObj() { Id=new Guid("36473164-C9E4-4CDF-B266-A0B287C85623"), Text = "First Guid Object" }; - var obj2 = new TestObj() { Id=new Guid("BC5C4C4A-CA57-4B61-8B53-9FD4673528B6"), Text = "Second Guid Object" }; + var guid1 = new Guid("36473164-C9E4-4CDF-B266-A0B287C85623"); + var guid2 = new Guid("BC5C4C4A-CA57-4B61-8B53-9FD4673528B6"); - var numIn1 = db.Insert(obj1); - var numIn2 = db.Insert(obj2); - Assert.AreEqual(1, numIn1); - Assert.AreEqual(1, numIn2); + var obj1 = new TestObj + { + Text = "First Guid Object" + }; + var obj2 = new TestObj + { + Text = "Second Guid Object" + }; - var result = db.Query("select * from TestObj").ToList(); - Assert.AreEqual(2, result.Count); - Assert.AreEqual(obj1.Text, result[0].Text); - Assert.AreEqual(obj2.Text, result[1].Text); + Assert.AreEqual(Guid.Empty, obj1.Id); + Assert.AreEqual(Guid.Empty, obj2.Id); - Assert.AreEqual(obj1.Id, result[0].Id); - Assert.AreEqual(obj2.Id, result[1].Id); + int numIn1 = db.Insert(obj1); + int numIn2 = db.Insert(obj2); + Assert.AreNotEqual(Guid.Empty, obj1.Id); + Assert.AreNotEqual(Guid.Empty, obj2.Id); + Assert.AreNotEqual(obj1.Id, obj2.Id); db.Close(); } @@ -61,17 +80,25 @@ public void ShouldPersistAndReadGuid() { [Test] public void AutoGuid_HasGuid() { - var db = new SQLiteConnection(TestPath.GetTempFileName()); + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); db.CreateTable(CreateFlags.AutoIncPK); var guid1 = new Guid("36473164-C9E4-4CDF-B266-A0B287C85623"); var guid2 = new Guid("BC5C4C4A-CA57-4B61-8B53-9FD4673528B6"); - var obj1 = new TestObj() { Id = guid1, Text = "First Guid Object" }; - var obj2 = new TestObj() { Id = guid2, Text = "Second Guid Object" }; - - var numIn1 = db.Insert(obj1); - var numIn2 = db.Insert(obj2); + var obj1 = new TestObj + { + Id = guid1, + Text = "First Guid Object" + }; + var obj2 = new TestObj + { + Id = guid2, + Text = "Second Guid Object" + }; + + int numIn1 = db.Insert(obj1); + int numIn2 = db.Insert(obj2); Assert.AreEqual(guid1, obj1.Id); Assert.AreEqual(guid2, obj2.Id); @@ -79,27 +106,35 @@ public void AutoGuid_HasGuid() } [Test] - public void AutoGuid_EmptyGuid() + public void ShouldPersistAndReadGuid() { - var db = new SQLiteConnection(TestPath.GetTempFileName()); - db.CreateTable(CreateFlags.AutoIncPK); - - var guid1 = new Guid("36473164-C9E4-4CDF-B266-A0B287C85623"); - var guid2 = new Guid("BC5C4C4A-CA57-4B61-8B53-9FD4673528B6"); + var db = new TestDb(TestPath.GetTempFileName()); - var obj1 = new TestObj() { Text = "First Guid Object" }; - var obj2 = new TestObj() { Text = "Second Guid Object" }; + var obj1 = new TestObj + { + Id = new Guid("36473164-C9E4-4CDF-B266-A0B287C85623"), + Text = "First Guid Object" + }; + var obj2 = new TestObj + { + Id = new Guid("BC5C4C4A-CA57-4B61-8B53-9FD4673528B6"), + Text = "Second Guid Object" + }; + + int numIn1 = db.Insert(obj1); + int numIn2 = db.Insert(obj2); + Assert.AreEqual(1, numIn1); + Assert.AreEqual(1, numIn2); - Assert.AreEqual(Guid.Empty, obj1.Id); - Assert.AreEqual(Guid.Empty, obj2.Id); + List result = db.Query("select * from TestObj").ToList(); + Assert.AreEqual(2, result.Count); + Assert.AreEqual(obj1.Text, result[0].Text); + Assert.AreEqual(obj2.Text, result[1].Text); - var numIn1 = db.Insert(obj1); - var numIn2 = db.Insert(obj2); - Assert.AreNotEqual(Guid.Empty, obj1.Id); - Assert.AreNotEqual(Guid.Empty, obj2.Id); - Assert.AreNotEqual(obj1.Id, obj2.Id); + Assert.AreEqual(obj1.Id, result[0].Id); + Assert.AreEqual(obj2.Id, result[1].Id); db.Close(); } } -} +} \ No newline at end of file diff --git a/tests/IgnoreTest.cs b/tests/IgnoreTest.cs new file mode 100644 index 000000000..6ce65b83a --- /dev/null +++ b/tests/IgnoreTest.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using SQLite.Net.Attributes; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; +#endif + + +namespace SQLite.Net.Tests +{ + [TestFixture] + public class IgnoredTest + { + public class DummyClass + { + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + + public string Foo { get; set; } + public string Bar { get; set; } + + [Attributes.Ignore] + public List Ignored { get; set; } + } + + [Test] + public void NullableFloat() + { + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); + // if the Ignored property is not ignore this will cause an exception + db.CreateTable(); + } + } +} \ No newline at end of file diff --git a/tests/InheritanceTest.cs b/tests/InheritanceTest.cs index 1705d77e7..6b9734084 100644 --- a/tests/InheritanceTest.cs +++ b/tests/InheritanceTest.cs @@ -1,44 +1,34 @@ -using System; -using System.Linq; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; -#endif - +using SQLite.Net.Attributes; -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class InheritanceTest - { - class Base - { - [PrimaryKey] - public int Id { get; set; } - - public string BaseProp { get; set; } - } - - class Derived : Base - { - public string DerivedProp { get; set; } - } - - - [Test] - public void InheritanceWorks () - { - var db = new TestDb (); - - var mapping = db.GetMapping (); - - Assert.AreEqual (3, mapping.Columns.Length); - Assert.AreEqual ("Id", mapping.PK.Name); - } - } -} + [TestFixture] + public class InheritanceTest + { + private class Base + { + [PrimaryKey] + public int Id { get; set; } + + public string BaseProp { get; set; } + } + + private class Derived : Base + { + public string DerivedProp { get; set; } + } + + + [Test] + public void InheritanceWorks() + { + var db = new TestDb(); + + TableMapping mapping = db.GetMapping(); + + Assert.AreEqual(3, mapping.Columns.Length); + Assert.AreEqual("Id", mapping.PK.Name); + } + } +} \ No newline at end of file diff --git a/tests/InsertTest.cs b/tests/InsertTest.cs index 144f8a44b..2c5dd762c 100644 --- a/tests/InsertTest.cs +++ b/tests/InsertTest.cs @@ -1,54 +1,71 @@ - using System; -using System.IO; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; -using System.Text; -using SQLite; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TearDown = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestCleanupAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; +using SQLite.Net.Attributes; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -using System.Diagnostics; -namespace SQLite.Tests -{ +namespace SQLite.Net.Tests +{ [TestFixture] public class InsertTest { + [SetUp] + public void Setup() + { + _db = new TestDb(TestPath.GetTempFileName()); + } + + [TearDown] + public void TearDown() + { + if (_db != null) + { + _db.Close(); + } + } + private TestDb _db; public class TestObj { [AutoIncrement, PrimaryKey] public int Id { get; set; } + public String Text { get; set; } - public override string ToString () + public override string ToString() { - return string.Format("[TestObj: Id={0}, Text={1}]", Id, Text); + return string.Format("[TestObj: Id={0}, Text={1}]", Id, Text); } - } public class TestObj2 { [PrimaryKey] public int Id { get; set; } + public String Text { get; set; } public override string ToString() { return string.Format("[TestObj: Id={0}, Text={1}]", Id, Text); } - } public class OneColumnObj @@ -57,135 +74,111 @@ public class OneColumnObj public int Id { get; set; } } - public class UniqueObj - { - [PrimaryKey] - public int Id { get; set; } - } + public class UniqueObj + { + [PrimaryKey] + public int Id { get; set; } + } public class TestDb : SQLiteConnection { public TestDb(String path) - : base(path) + : base(new SQLitePlatformTest(), path) { - CreateTable(); + CreateTable(); CreateTable(); CreateTable(); - CreateTable(); + CreateTable(); } } - - [SetUp] - public void Setup() - { - _db = new TestDb(TestPath.GetTempFileName()); - } - [TearDown] - public void TearDown() - { - if (_db != null) _db.Close(); - } [Test] public void InsertALot() { - int n = 10000; - var q = from i in Enumerable.Range(1, n) - select new TestObj() { - Text = "I am" - }; - var objs = q.ToArray(); - _db.Trace = false; - - var sw = new Stopwatch(); - sw.Start(); - - var numIn = _db.InsertAll(objs); - - sw.Stop(); - - Assert.AreEqual(numIn, n, "Num inserted must = num objects"); - - var inObjs = _db.CreateCommand("select * from TestObj").ExecuteQuery().ToArray(); - - for (var i = 0; i < inObjs.Length; i++) { - Assert.AreEqual(i+1, objs[i].Id); - Assert.AreEqual(i+1, inObjs[i].Id); - Assert.AreEqual("I am", inObjs[i].Text); - } - - var numCount = _db.CreateCommand("select count(*) from TestObj").ExecuteScalar(); - - Assert.AreEqual(numCount, n, "Num counted must = num objects"); + int n = 10000; + IEnumerable q = from i in Enumerable.Range(1, n) + select new TestObj + { + Text = "I am" + }; + TestObj[] objs = q.ToArray(); + _db.TraceListener = DebugTraceListener.Instance; + + var sw = new Stopwatch(); + sw.Start(); + + int numIn = _db.InsertAll(objs); + + sw.Stop(); + + Assert.AreEqual(numIn, n, "Num inserted must = num objects"); + + TestObj[] inObjs = _db.CreateCommand("select * from TestObj").ExecuteQuery().ToArray(); + + for (int i = 0; i < inObjs.Length; i++) + { + Assert.AreEqual(i + 1, objs[i].Id); + Assert.AreEqual(i + 1, inObjs[i].Id); + Assert.AreEqual("I am", inObjs[i].Text); + } + + var numCount = _db.CreateCommand("select count(*) from TestObj").ExecuteScalar(); + + Assert.AreEqual(numCount, n, "Num counted must = num objects"); } [Test] - public void InsertTwoTimes() + public void InsertAllFailureInsideTransaction() { - var obj1 = new TestObj() { Text = "GLaDOS loves testing!" }; - var obj2 = new TestObj() { Text = "Keep testing, just keep testing" }; - + List testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj + { + Id = i + }).ToList(); + testObjects[testObjects.Count - 1].Id = 1; // causes the insert to fail because of duplicate key - var numIn1 = _db.Insert(obj1); - var numIn2 = _db.Insert(obj2); - Assert.AreEqual(1, numIn1); - Assert.AreEqual(1, numIn2); + ExceptionAssert.Throws(() => _db.RunInTransaction(() => { _db.InsertAll(testObjects); })); - var result = _db.Query("select * from TestObj").ToList(); - Assert.AreEqual(2, result.Count); - Assert.AreEqual(obj1.Text, result[0].Text); - Assert.AreEqual(obj2.Text, result[1].Text); + Assert.AreEqual(0, _db.Table().Count()); } [Test] - public void InsertIntoTwoTables() + public void InsertAllFailureOutsideTransaction() { - var obj1 = new TestObj() { Text = "GLaDOS loves testing!" }; - var obj2 = new TestObj2() { Text = "Keep testing, just keep testing" }; + List testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj + { + Id = i + }).ToList(); + testObjects[testObjects.Count - 1].Id = 1; // causes the insert to fail because of duplicate key - var numIn1 = _db.Insert(obj1); - Assert.AreEqual(1, numIn1); - var numIn2 = _db.Insert(obj2); - Assert.AreEqual(1, numIn2); + ExceptionAssert.Throws(() => _db.InsertAll(testObjects)); - var result1 = _db.Query("select * from TestObj").ToList(); - Assert.AreEqual(numIn1, result1.Count); - Assert.AreEqual(obj1.Text, result1.First().Text); - - var result2 = _db.Query("select * from TestObj2").ToList(); - Assert.AreEqual(numIn2, result2.Count); + Assert.AreEqual(0, _db.Table().Count()); } [Test] - public void InsertWithExtra() + public void InsertAllSuccessInsideTransaction() { - var obj1 = new TestObj2() { Id=1, Text = "GLaDOS loves testing!" }; - var obj2 = new TestObj2() { Id=1, Text = "Keep testing, just keep testing" }; - var obj3 = new TestObj2() { Id=1, Text = "Done testing" }; + List testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj + { + Id = i + }).ToList(); - _db.Insert(obj1); - - - try { - _db.Insert(obj2); - Assert.Fail("Expected unique constraint violation"); - } - catch (SQLiteException) { - } - _db.Insert(obj2, "OR REPLACE"); + _db.RunInTransaction(() => { _db.InsertAll(testObjects); }); + Assert.AreEqual(testObjects.Count, _db.Table().Count()); + } - try { - _db.Insert(obj3); - Assert.Fail("Expected unique constraint violation"); - } - catch (SQLiteException) { - } - _db.Insert(obj3, "OR IGNORE"); + [Test] + public void InsertAllSuccessOutsideTransaction() + { + List testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj + { + Id = i + }).ToList(); - var result = _db.Query("select * from TestObj2").ToList(); - Assert.AreEqual(1, result.Count); - Assert.AreEqual(obj2.Text, result.First().Text); + _db.InsertAll(testObjects); + + Assert.AreEqual(testObjects.Count, _db.Table().Count()); } [Test] @@ -198,66 +191,125 @@ public void InsertIntoOneColumnAutoIncrementTable() Assert.AreEqual(1, result.Id); } - [Test] - public void InsertAllSuccessOutsideTransaction() - { - var testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj { Id = i }).ToList(); + [Test] + public void InsertIntoTwoTables() + { + var obj1 = new TestObj + { + Text = "GLaDOS loves testing!" + }; + var obj2 = new TestObj2 + { + Text = "Keep testing, just keep testing" + }; - _db.InsertAll(testObjects); + int numIn1 = _db.Insert(obj1); + Assert.AreEqual(1, numIn1); + int numIn2 = _db.Insert(obj2); + Assert.AreEqual(1, numIn2); - Assert.AreEqual(testObjects.Count, _db.Table().Count()); - } + List result1 = _db.Query("select * from TestObj").ToList(); + Assert.AreEqual(numIn1, result1.Count); + Assert.AreEqual(obj1.Text, result1.First().Text); - [Test] - public void InsertAllFailureOutsideTransaction() - { - var testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj { Id = i }).ToList(); - testObjects[testObjects.Count - 1].Id = 1; // causes the insert to fail because of duplicate key + List result2 = _db.Query("select * from TestObj2").ToList(); + Assert.AreEqual(numIn2, result2.Count); + } - ExceptionAssert.Throws(() => _db.InsertAll(testObjects)); + [Test] + public void InsertOrReplace() + { + _db.TraceListener = DebugTraceListener.Instance; + _db.InsertAll(from i in Enumerable.Range(1, 20) + select new TestObj + { + Text = "#" + i + }); - Assert.AreEqual(0, _db.Table().Count()); - } + Assert.AreEqual(20, _db.Table().Count()); - [Test] - public void InsertAllSuccessInsideTransaction() - { - var testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj { Id = i }).ToList(); + var t = new TestObj + { + Id = 5, + Text = "Foo", + }; + _db.InsertOrReplace(t); + + List r = (from x in _db.Table() orderby x.Id select x).ToList(); + Assert.AreEqual(20, r.Count); + Assert.AreEqual("Foo", r[4].Text); + } - _db.RunInTransaction(() => { - _db.InsertAll(testObjects); - }); + [Test] + public void InsertTwoTimes() + { + var obj1 = new TestObj + { + Text = "GLaDOS loves testing!" + }; + var obj2 = new TestObj + { + Text = "Keep testing, just keep testing" + }; - Assert.AreEqual(testObjects.Count, _db.Table().Count()); - } - [Test] - public void InsertAllFailureInsideTransaction() - { - var testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj { Id = i }).ToList(); - testObjects[testObjects.Count - 1].Id = 1; // causes the insert to fail because of duplicate key + int numIn1 = _db.Insert(obj1); + int numIn2 = _db.Insert(obj2); + Assert.AreEqual(1, numIn1); + Assert.AreEqual(1, numIn2); - ExceptionAssert.Throws(() => _db.RunInTransaction(() => { - _db.InsertAll(testObjects); - })); + List result = _db.Query("select * from TestObj").ToList(); + Assert.AreEqual(2, result.Count); + Assert.AreEqual(obj1.Text, result[0].Text); + Assert.AreEqual(obj2.Text, result[1].Text); + } - Assert.AreEqual(0, _db.Table().Count()); - } + [Test] + public void InsertWithExtra() + { + var obj1 = new TestObj2 + { + Id = 1, + Text = "GLaDOS loves testing!" + }; + var obj2 = new TestObj2 + { + Id = 1, + Text = "Keep testing, just keep testing" + }; + var obj3 = new TestObj2 + { + Id = 1, + Text = "Done testing" + }; - [Test] - public void InsertOrReplace () - { - _db.Trace = true; - _db.InsertAll (from i in Enumerable.Range(1, 20) select new TestObj { Text = "#" + i }); + _db.Insert(obj1); - Assert.AreEqual (20, _db.Table ().Count ()); - var t = new TestObj { Id = 5, Text = "Foo", }; - _db.InsertOrReplace (t); + try + { + _db.Insert(obj2); + Assert.Fail("Expected unique constraint violation"); + } + catch (SQLiteException) + { + } + _db.Insert(obj2, "OR REPLACE"); + + + try + { + _db.Insert(obj3); + Assert.Fail("Expected unique constraint violation"); + } + catch (SQLiteException) + { + } + _db.Insert(obj3, "OR IGNORE"); - var r = (from x in _db.Table () orderby x.Id select x).ToList (); - Assert.AreEqual (20, r.Count); - Assert.AreEqual ("Foo", r[4].Text); - } + List result = _db.Query("select * from TestObj2").ToList(); + Assert.AreEqual(1, result.Count); + Assert.AreEqual(obj2.Text, result.First().Text); + } } -} +} \ No newline at end of file diff --git a/tests/JoinTest.cs b/tests/JoinTest.cs index db3f31a53..91e7a758b 100644 --- a/tests/JoinTest.cs +++ b/tests/JoinTest.cs @@ -1,92 +1,107 @@ using System; -using System.IO; -using System.Collections.Generic; -//using System.Linq; -using System.Text; -using SQLite; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SetUp = Microsoft.VisualStudio.TestTools.UnitTesting.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute; -#else +using System.Linq; using NUnit.Framework; -#endif - -using System.Diagnostics; -namespace SQLite.Tests -{ +namespace SQLite.Net.Tests +{ [TestFixture] public class JoinTest { - TestDb _db; - - [SetUp] - public void SetUp () - { - _db = new TestDb (); - _db.CreateTable (); - _db.CreateTable (); - _db.CreateTable (); - - var p1 = new Product { Name = "One", }; - var p2 = new Product { Name = "Two", }; - var p3 = new Product { Name = "Three", }; - _db.InsertAll (new [] { p1, p2, p3 } ); - - var o1 = new Order { PlacedTime = DateTime.Now, }; - var o2 = new Order { PlacedTime = DateTime.Now, }; - _db.InsertAll (new [] { o1, o2 } ); - - _db.InsertAll (new [] { - new OrderLine { - OrderId = o1.Id, - ProductId = p1.Id, - Quantity = 1, - }, - new OrderLine { - OrderId = o1.Id, - ProductId = p2.Id, - Quantity = 2, - }, - new OrderLine { - OrderId = o2.Id, - ProductId = p3.Id, - Quantity = 3, - }, - }); - } - - class R - { - } - - //[Test] - public void JoinThenWhere () - { - var q = from ol in _db.Table () - join o in _db.Table () on ol.OrderId equals o.Id - where o.Id == 1 - select new { o.Id, ol.ProductId, ol.Quantity }; - - var r = System.Linq.Enumerable.ToList (q); - - Assert.AreEqual (2, r.Count); - } - - //[Test] - public void WhereThenJoin () - { - var q = from ol in _db.Table () - where ol.OrderId == 1 - join o in _db.Table () on ol.OrderId equals o.Id - select new { o.Id, ol.ProductId, ol.Quantity }; - - var r = System.Linq.Enumerable.ToList (q); - - Assert.AreEqual (2, r.Count); - } - } -} + [SetUp] + public void SetUp() + { + _db = new TestDb(); + _db.CreateTable(); + _db.CreateTable(); + _db.CreateTable(); + + var p1 = new Product + { + Name = "One", + }; + var p2 = new Product + { + Name = "Two", + }; + var p3 = new Product + { + Name = "Three", + }; + _db.InsertAll(new[] {p1, p2, p3}); + + var o1 = new Order + { + PlacedTime = DateTime.Now, + }; + var o2 = new Order + { + PlacedTime = DateTime.Now, + }; + _db.InsertAll(new[] {o1, o2}); + + _db.InsertAll(new[] + { + new OrderLine + { + OrderId = o1.Id, + ProductId = p1.Id, + Quantity = 1, + }, + new OrderLine + { + OrderId = o1.Id, + ProductId = p2.Id, + Quantity = 2, + }, + new OrderLine + { + OrderId = o2.Id, + ProductId = p3.Id, + Quantity = 3, + } + }); + } + + private TestDb _db; + + private class R + { + } + + //[Test] + public void JoinThenWhere() + { + var q = from ol in _db.Table() + join o in _db.Table() on ol.OrderId equals o.Id + where o.Id == 1 + select new + { + o.Id, + ol.ProductId, + ol.Quantity + }; + + var r = q.ToList(); + + Assert.AreEqual(2, r.Count); + } + + //[Test] + public void WhereThenJoin() + { + var q = from ol in _db.Table() + where ol.OrderId == 1 + join o in _db.Table() on ol.OrderId equals o.Id + select new + { + o.Id, + ol.ProductId, + ol.Quantity + }; + + var r = q.ToList(); + + Assert.AreEqual(2, r.Count); + } + } +} \ No newline at end of file diff --git a/tests/LinqTest.cs b/tests/LinqTest.cs index 0ca18ba6e..5a27b01a7 100644 --- a/tests/LinqTest.cs +++ b/tests/LinqTest.cs @@ -1,187 +1,195 @@ using System; -using System.Linq; using System.Collections.Generic; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else +using System.Linq; using NUnit.Framework; -#endif +using SQLite.Net.Attributes; -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class LinqTest - { - TestDb CreateDb () - { - var db = new TestDb (); - db.CreateTable (); - db.CreateTable (); - db.CreateTable (); - db.CreateTable (); - return db; - } - - [Test] - public void FunctionParameter () - { - var db = CreateDb (); - - db.Insert (new Product { - Name = "A", - Price = 20, - }); - - db.Insert (new Product { - Name = "B", - Price = 10, - }); - - Func> GetProductsWithPriceAtLeast = delegate(decimal val) { - return (from p in db.Table () where p.Price > val select p).ToList (); - }; - - var r = GetProductsWithPriceAtLeast (15); - Assert.AreEqual (1, r.Count); - Assert.AreEqual ("A", r [0].Name); - } - - [Test] - public void WhereGreaterThan () - { - var db = CreateDb (); - - db.Insert (new Product { - Name = "A", - Price = 20, - }); - - db.Insert (new Product { - Name = "B", - Price = 10, - }); - - Assert.AreEqual (2, db.Table ().Count ()); - - var r = (from p in db.Table () where p.Price > 15 select p).ToList (); - Assert.AreEqual (1, r.Count); - Assert.AreEqual ("A", r [0].Name); - } - - [Test] - public void GetWithExpression () - { - var db = CreateDb(); - - db.Insert (new Product { - Name = "A", - Price = 20, - }); - - db.Insert (new Product { - Name = "B", - Price = 10, - }); + [TestFixture] + public class LinqTest + { + private TestDb CreateDb() + { + var db = new TestDb(); + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + return db; + } + + public class Issue96_A + { + [AutoIncrement, PrimaryKey] + public int ID { get; set; } + + public string AddressLine { get; set; } + + [Indexed] + public int? ClassB { get; set; } + + [Indexed] + public int? ClassC { get; set; } + } + + public class Issue96_B + { + [AutoIncrement, PrimaryKey] + public int ID { get; set; } + + public string CustomerName { get; set; } + } + + public class Issue96_C + { + [AutoIncrement, PrimaryKey] + public int ID { get; set; } + + public string SupplierName { get; set; } + } + + [Test] + public void FindWithExpression() + { + TestDb db = CreateDb(); + + var r = db.Find(x => x.Price == 10); + Assert.IsNull(r); + } + + [Test] + public void FunctionParameter() + { + TestDb db = CreateDb(); + + db.Insert(new Product + { + Name = "A", + Price = 20, + }); + + db.Insert(new Product + { + Name = "B", + Price = 10, + }); + + Func> GetProductsWithPriceAtLeast = + delegate(decimal val) { return (from p in db.Table() where p.Price > val select p).ToList(); }; + + List r = GetProductsWithPriceAtLeast(15); + Assert.AreEqual(1, r.Count); + Assert.AreEqual("A", r[0].Name); + } + + [Test] + public void GetWithExpression() + { + TestDb db = CreateDb(); + + db.Insert(new Product + { + Name = "A", + Price = 20, + }); + + db.Insert(new Product + { + Name = "B", + Price = 10, + }); db.Insert(new Product { Name = "C", Price = 5, }); - - Assert.AreEqual (3, db.Table ().Count ()); - - var r = db.Get(x => x.Price == 10); + + Assert.AreEqual(3, db.Table().Count()); + + var r = db.Get(x => x.Price == 10); Assert.IsNotNull(r); - Assert.AreEqual ("B", r.Name); - } - - [Test] - public void FindWithExpression () - { - var db = CreateDb(); - - var r = db.Find (x => x.Price == 10); - Assert.IsNull (r); - } - - [Test] - public void OrderByCast () - { - var db = CreateDb(); - - db.Insert (new Product { - Name = "A", - TotalSales = 1, - }); - db.Insert (new Product { - Name = "B", - TotalSales = 100, - }); - - var nocast = (from p in db.Table () orderby p.TotalSales descending select p).ToList (); - Assert.AreEqual (2, nocast.Count); - Assert.AreEqual ("B", nocast [0].Name); - - var cast = (from p in db.Table () orderby (int)p.TotalSales descending select p).ToList (); - Assert.AreEqual (2, cast.Count); - Assert.AreEqual ("B", cast [0].Name); - } - - public class Issue96_A - { - [ AutoIncrement, PrimaryKey] - public int ID { get; set; } - public string AddressLine { get; set; } - - [Indexed] - public int? ClassB { get; set; } - [Indexed] - public int? ClassC { get; set; } - } - - public class Issue96_B - { - [ AutoIncrement, PrimaryKey] - public int ID { get; set; } - public string CustomerName { get; set; } - } - - public class Issue96_C - { - [ AutoIncrement, PrimaryKey] - public int ID { get; set; } - public string SupplierName { get; set; } - } - - [Test] - public void Issue96_NullabelIntsInQueries () - { - var db = CreateDb(); - db.CreateTable (); - - var id = 42; - - db.Insert (new Issue96_A { - ClassB = id, - }); - db.Insert (new Issue96_A { - ClassB = null, - }); - db.Insert (new Issue96_A { - ClassB = null, - }); - db.Insert (new Issue96_A { - ClassB = null, - }); - - - Assert.AreEqual (1, db.Table().Where(p => p.ClassB == id).Count ()); - Assert.AreEqual (3, db.Table().Where(p => p.ClassB == null).Count ()); - } - } -} + Assert.AreEqual("B", r.Name); + } + + [Test] + public void Issue96_NullabelIntsInQueries() + { + TestDb db = CreateDb(); + db.CreateTable(); + + int id = 42; + + db.Insert(new Issue96_A + { + ClassB = id, + }); + db.Insert(new Issue96_A + { + ClassB = null, + }); + db.Insert(new Issue96_A + { + ClassB = null, + }); + db.Insert(new Issue96_A + { + ClassB = null, + }); + + + Assert.AreEqual(1, db.Table().Where(p => p.ClassB == id).Count()); + Assert.AreEqual(3, db.Table().Where(p => p.ClassB == null).Count()); + } + + [Test] + public void OrderByCast() + { + TestDb db = CreateDb(); + + db.Insert(new Product + { + Name = "A", + TotalSales = 1, + }); + db.Insert(new Product + { + Name = "B", + TotalSales = 100, + }); + + List nocast = (from p in db.Table() orderby p.TotalSales descending select p).ToList(); + Assert.AreEqual(2, nocast.Count); + Assert.AreEqual("B", nocast[0].Name); + + List cast = (from p in db.Table() orderby (int) p.TotalSales descending select p).ToList(); + Assert.AreEqual(2, cast.Count); + Assert.AreEqual("B", cast[0].Name); + } + + [Test] + public void WhereGreaterThan() + { + TestDb db = CreateDb(); + + db.Insert(new Product + { + Name = "A", + Price = 20, + }); + + db.Insert(new Product + { + Name = "B", + Price = 10, + }); + + Assert.AreEqual(2, db.Table().Count()); + + List r = (from p in db.Table() where p.Price > 15 select p).ToList(); + Assert.AreEqual(1, r.Count); + Assert.AreEqual("A", r[0].Name); + } + } +} \ No newline at end of file diff --git a/tests/MappingTest.cs b/tests/MappingTest.cs index df5d0272f..3bf5f6aaa 100644 --- a/tests/MappingTest.cs +++ b/tests/MappingTest.cs @@ -1,74 +1,67 @@ -using System; using System.Collections.Generic; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; -#endif +using SQLite.Net.Attributes; -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class MappingTest - { - [Table ("AGoodTableName")] - class AFunnyTableName - { - [PrimaryKey] - public int Id { get; set; } - - [Column ("AGoodColumnName")] - public string AFunnyColumnName { get; set; } - } - - - [Test] - public void HasGoodNames () - { - var db = new TestDb (); - - db.CreateTable (); - - var mapping = db.GetMapping (); - - Assert.AreEqual ("AGoodTableName", mapping.TableName); - - Assert.AreEqual ("Id", mapping.Columns [0].Name); - Assert.AreEqual ("AGoodColumnName", mapping.Columns [1].Name); - } - - #region Issue #86 - - [Table("foo")] - public class Foo - { - [Column("baz")] - public int Bar { get; set; } - } - - [Test] - public void Issue86 () - { - var db = new TestDb (); - db.CreateTable (); - - db.Insert (new Foo { Bar = 42 } ); - db.Insert (new Foo { Bar = 69 } ); - - var found42 = db.Table ().Where (f => f.Bar == 42).FirstOrDefault(); - Assert.IsNotNull (found42); - - var ordered = new List(db.Table().OrderByDescending(f => f.Bar)); - Assert.AreEqual(2, ordered.Count); - Assert.AreEqual(69, ordered[0].Bar); - Assert.AreEqual(42, ordered[1].Bar); - } - - #endregion - } -} - + [TestFixture] + public class MappingTest + { + [Table("AGoodTableName")] + private class AFunnyTableName + { + [PrimaryKey] + public int Id { get; set; } + + [Column("AGoodColumnName")] + public string AFunnyColumnName { get; set; } + } + + + [Table("foo")] + public class Foo + { + [Column("baz")] + public int Bar { get; set; } + } + + [Test] + public void HasGoodNames() + { + var db = new TestDb(); + + db.CreateTable(); + + TableMapping mapping = db.GetMapping(); + + Assert.AreEqual("AGoodTableName", mapping.TableName); + + Assert.AreEqual("Id", mapping.Columns[0].Name); + Assert.AreEqual("AGoodColumnName", mapping.Columns[1].Name); + } + + [Test] + public void Issue86() + { + var db = new TestDb(); + db.CreateTable(); + + db.Insert(new Foo + { + Bar = 42 + }); + db.Insert(new Foo + { + Bar = 69 + }); + + Foo found42 = db.Table().Where(f => f.Bar == 42).FirstOrDefault(); + Assert.IsNotNull(found42); + + var ordered = new List(db.Table().OrderByDescending(f => f.Bar)); + Assert.AreEqual(2, ordered.Count); + Assert.AreEqual(69, ordered[0].Bar); + Assert.AreEqual(42, ordered[1].Bar); + } + } +} \ No newline at end of file diff --git a/tests/MigrationTest.cs b/tests/MigrationTest.cs index c304dc2bf..2625cd27d 100644 --- a/tests/MigrationTest.cs +++ b/tests/MigrationTest.cs @@ -1,43 +1,40 @@ +using System.Collections.Generic; using System.Linq; -using System.Text; -using SQLite; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; -#endif - -using System.IO; +using SQLite.Net.Attributes; -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class MigrationTest - { - [Table ("Test")] - class LowerId { - public int Id { get; set; } - } - [Table ("Test")] - class UpperId { - public int ID { get; set; } - } + [TestFixture] + public class MigrationTest + { + [Table("Test")] + private class LowerId + { + public int Id { get; set; } + } + + [Table("Test")] + private class UpperId + { + public int ID { get; set; } + } - [Test] - public void UpperAndLowerColumnNames () - { - using (var db = new TestDb (true) { Trace = true } ) { - db.CreateTable (); - db.CreateTable (); + [Test] + public void UpperAndLowerColumnNames() + { + using (var db = new TestDb(true) + { + TraceListener = DebugTraceListener.Instance + }) + { + db.CreateTable(); + db.CreateTable(); - var cols = db.GetTableInfo ("Test").ToList (); - Assert.That (cols.Count, Is.EqualTo (1)); - Assert.That (cols[0].Name, Is.EqualTo ("Id")); - } - } - } -} + List cols = db.GetTableInfo("Test").ToList(); + Assert.That(cols.Count, Is.EqualTo(1)); + Assert.That(cols[0].Name, Is.EqualTo("Id")); + } + } + } +} \ No newline at end of file diff --git a/tests/NotNullAttributeTest.cs b/tests/NotNullAttributeTest.cs new file mode 100644 index 000000000..bac36860f --- /dev/null +++ b/tests/NotNullAttributeTest.cs @@ -0,0 +1,358 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using NUnit.Framework; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; +#endif + +namespace SQLite.Net.Tests +{ + [TestFixture] + public class NotNullAttributeTest + { + private class NotNullNoPK + { + [PrimaryKey, AutoIncrement] + public int? objectId { get; set; } + [NotNull] + public int? RequiredIntProp { get; set; } + public int? OptionalIntProp { get; set; } + [NotNull] + public string RequiredStringProp { get; set; } + public string OptionalStringProp { get; set; } + [NotNull] + public string AnotherRequiredStringProp { get; set; } + } + + private class ClassWithPK + { + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + } + + private IEnumerable GetExpectedColumnInfos(IReflectionService reflectionService, Type type) + { + var expectedValues = from prop in reflectionService.GetPublicInstanceProperties(type) + select new SQLiteConnection.ColumnInfo + { + Name = prop.Name, + notnull = ((!prop.GetCustomAttributes(true).Any()) && (!prop.GetCustomAttributes(true).Any())) ? 0 : 1 + }; + + return expectedValues; + } + + [Test] + public void PrimaryKeyHasNotNullConstraint() + { + using (TestDb db = new TestDb()) + { + + db.CreateTable(); + var cols = db.GetTableInfo("ClassWithPK"); + + var joined = from expected in GetExpectedColumnInfos(db.Platform.ReflectionService, typeof(ClassWithPK)) + join actual in cols on expected.Name equals actual.Name + where actual.notnull != expected.notnull + select actual.Name; + + Assert.AreNotEqual(0, cols.Count(), "Failed to get table info"); + Assert.IsTrue(joined.Count() == 0, string.Format("not null constraint was not created for the following properties: {0}" + , string.Join(", ", joined.ToArray()))); + } + } + + [Test] + public void CreateTableWithNotNullConstraints() + { + using (var db = new TestDb()) + { + db.CreateTable(); + var cols = db.GetTableInfo("NotNullNoPK"); + + var joined = from expected in GetExpectedColumnInfos(db.Platform.ReflectionService, typeof(NotNullNoPK)) + join actual in cols on expected.Name equals actual.Name + where actual.notnull != expected.notnull + select actual.Name; + + Assert.AreNotEqual(0, cols.Count(), "Failed to get table info"); + Assert.IsTrue(joined.Count() == 0, string.Format("not null constraint was not created for the following properties: {0}" + , string.Join(", ", joined.ToArray()))); + } + } + + [Test] + public void InsertWithNullsThrowsException() + { + using (TestDb db = new TestDb()) + { + db.CreateTable(); + + try + { + NotNullNoPK obj = new NotNullNoPK(); + db.Insert(obj); + } + catch (NotNullConstraintViolationException) + { + return; + } + catch (SQLiteException ex) + { + if (db.Platform.SQLiteApi.LibVersionNumber() < 3007017 && ex.Result == Result.Constraint) + { + Assert.Inconclusive("Detailed constraint information is only available in SQLite3 version 3.7.17 and above."); + } + } + } + Assert.Fail("Expected an exception of type NotNullConstraintViolationException to be thrown. No exception was thrown."); + } + + + [Test] + public void UpdateWithNullThrowsException() + { + using (TestDb db = new TestDb()) + { + + db.CreateTable(); + + try + { + NotNullNoPK obj = new NotNullNoPK() + { + AnotherRequiredStringProp = "Another required string", + RequiredIntProp = 123, + RequiredStringProp = "Required string" + }; + db.Insert(obj); + obj.RequiredStringProp = null; + db.Update(obj); + } + catch (NotNullConstraintViolationException) + { + return; + } + catch (SQLiteException ex) + { + if (db.Platform.SQLiteApi.LibVersionNumber() < 3007017 && ex.Result == Result.Constraint) + { + Assert.Inconclusive("Detailed constraint information is only available in SQLite3 version 3.7.17 and above."); + } + } + } + Assert.Fail("Expected an exception of type NotNullConstraintViolationException to be thrown. No exception was thrown."); + } + + [Test] + public void NotNullConstraintExceptionListsOffendingColumnsOnInsert() + { + using (TestDb db = new TestDb()) + { + + db.CreateTable(); + + try + { + NotNullNoPK obj = new NotNullNoPK() { RequiredStringProp = "Some value" }; + db.Insert(obj); + } + catch (NotNullConstraintViolationException ex) + { + string expected = "AnotherRequiredStringProp, RequiredIntProp"; + string actual = string.Join(", ", ex.Columns.Where(c => !c.IsPK).OrderBy(p => p.PropertyName).Select(c => c.PropertyName)); + + Assert.AreEqual(expected, actual, "NotNullConstraintViolationException did not correctly list the columns that violated the constraint"); + return; + } + catch (SQLiteException ex) + { + if (db.Platform.SQLiteApi.LibVersionNumber() < 3007017 && ex.Result == Result.Constraint) + { + Assert.Inconclusive("Detailed constraint information is only available in SQLite3 version 3.7.17 and above."); + } + } + Assert.Fail("Expected an exception of type NotNullConstraintViolationException to be thrown. No exception was thrown."); + } + } + + [Test] + public void NotNullConstraintExceptionListsOffendingColumnsOnUpdate() + { + using (TestDb db = new TestDb()) + { + // Skip this test if the Dll doesn't support the extended SQLITE_CONSTRAINT codes + if (db.Platform.SQLiteApi.LibVersionNumber() >= 3007017) + { + db.CreateTable(); + + try + { + NotNullNoPK obj = new NotNullNoPK() + { + AnotherRequiredStringProp = "Another required string", + RequiredIntProp = 123, + RequiredStringProp = "Required string" + }; + db.Insert(obj); + obj.RequiredStringProp = null; + db.Update(obj); + } + catch (NotNullConstraintViolationException ex) + { + string expected = "RequiredStringProp"; + string actual = string.Join(", ", ex.Columns.Where(c => !c.IsPK).OrderBy(p => p.PropertyName).Select(c => c.PropertyName)); + + Assert.AreEqual(expected, actual, "NotNullConstraintViolationException did not correctly list the columns that violated the constraint"); + + return; + } + catch (SQLiteException ex) + { + if (db.Platform.SQLiteApi.LibVersionNumber() < 3007017 && ex.Result == Result.Constraint) + { + Assert.Inconclusive("Detailed constraint information is only available in SQLite3 version 3.7.17 and above."); + } + } + catch (Exception ex) + { + Assert.Fail( + "Expected an exception of type NotNullConstraintViolationException to be thrown. An exception of type {0} was thrown instead.", + ex.GetType().Name); + } + Assert.Fail("Expected an exception of type NotNullConstraintViolationException to be thrown. No exception was thrown."); + } + } + } + + [Test] + public void InsertQueryWithNullThrowsException() + { + using (TestDb db = new TestDb()) + { + // Skip this test if the Dll doesn't support the extended SQLITE_CONSTRAINT codes + if (db.Platform.SQLiteApi.LibVersionNumber() >= 3007017) + { + db.CreateTable(); + + try + { + db.Execute("insert into \"NotNullNoPK\" (AnotherRequiredStringProp, RequiredIntProp, RequiredStringProp) values(?, ?, ?)", + new object[] {"Another required string", 123, null}); + } + catch (NotNullConstraintViolationException) + { + return; + } + catch (SQLiteException ex) + { + if (db.Platform.SQLiteApi.LibVersionNumber() < 3007017 && ex.Result == Result.Constraint) + { + Assert.Inconclusive("Detailed constraint information is only available in SQLite3 version 3.7.17 and above."); + } + } + catch (Exception ex) + { + Assert.Fail( + "Expected an exception of type NotNullConstraintViolationException to be thrown. An exception of type {0} was thrown instead.", + ex.GetType().Name); + } + } + Assert.Fail("Expected an exception of type NotNullConstraintViolationException to be thrown. No exception was thrown."); + } + } + + [Test] + public void UpdateQueryWithNullThrowsException() + { + // Skip this test if the Dll doesn't support the extended SQLITE_CONSTRAINT codes + using (TestDb db = new TestDb()) + { + + db.CreateTable(); + + try + { + db.Execute("insert into \"NotNullNoPK\" (AnotherRequiredStringProp, RequiredIntProp, RequiredStringProp) values(?, ?, ?)", + new object[] { "Another required string", 123, "Required string" }); + + db.Execute("update \"NotNullNoPK\" set AnotherRequiredStringProp=?, RequiredIntProp=?, RequiredStringProp=? where ObjectId=?", + new object[] { "Another required string", 123, null, 1 }); + } + catch (NotNullConstraintViolationException) + { + return; + } + catch (SQLiteException ex) + { + if (db.Platform.SQLiteApi.LibVersionNumber() < 3007017 && ex.Result == Result.Constraint) + { + Assert.Inconclusive("Detailed constraint information is only available in SQLite3 version 3.7.17 and above."); + } + } + catch (Exception ex) + { + Assert.Fail("Expected an exception of type NotNullConstraintViolationException to be thrown. An exception of type {0} was thrown instead.", ex.GetType().Name); + } + Assert.Fail("Expected an exception of type NotNullConstraintViolationException to be thrown. No exception was thrown."); + } + } + + [Test] + public void ExecuteNonQueryWithNullThrowsException() + { + using (TestDb db = new TestDb()) + { + TableMapping map; + + db.CreateTable(); + + try + { + NotNullNoPK obj = new NotNullNoPK() + { + AnotherRequiredStringProp = "Another required prop", + RequiredIntProp = 123, + RequiredStringProp = "Required string prop" + }; + db.Insert(obj); + + map = db.GetMapping(); + map.GetInsertCommand(db, "OR REPLACE").ExecuteNonQuery(new object[] { 1, null, 123, null, null, null }); + } + catch (NotNullConstraintViolationException) + { + return; + } + catch (SQLiteException ex) + { + if (db.Platform.SQLiteApi.LibVersionNumber() < 3007017 && ex.Result == Result.Constraint) + { + Assert.Inconclusive("Detailed constraint information is only available in SQLite3 version 3.7.17 and above."); + } + } + catch (Exception ex) + { + Assert.Fail("Expected an exception of type NotNullConstraintViolationException to be thrown. An exception of type {0} was thrown instead.", ex.GetType().Name); + } + } + Assert.Fail("Expected an exception of type NotNullConstraintViolationException to be thrown. No exception was thrown."); + } + + } +} \ No newline at end of file diff --git a/tests/NullableTest.cs b/tests/NullableTest.cs index 29e1e2575..81039ab9d 100644 --- a/tests/NullableTest.cs +++ b/tests/NullableTest.cs @@ -1,247 +1,366 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SQLite; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else +using System.Linq; using NUnit.Framework; +using SQLite.Net.Attributes; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -using System.IO; -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class NullableTest - { - public class NullableIntClass - { - [PrimaryKey, AutoIncrement] - public int ID { get; set; } - - public Nullable NullableInt { get; set; } - - public override bool Equals(object obj) - { - NullableIntClass other = (NullableIntClass)obj; - return this.ID == other.ID && this.NullableInt == other.NullableInt; - } - - public override int GetHashCode () - { - return ID.GetHashCode () + NullableInt.GetHashCode (); - } - } - - [Test] - [Description("Create a table with a nullable int column then insert and select against it")] - public void NullableInt() - { - SQLiteConnection db = new SQLiteConnection(TestPath.GetTempFileName()); - db.CreateTable(); - - NullableIntClass withNull = new NullableIntClass() { NullableInt = null }; - NullableIntClass with0 = new NullableIntClass() { NullableInt = 0 }; - NullableIntClass with1 = new NullableIntClass() { NullableInt = 1 }; - NullableIntClass withMinus1 = new NullableIntClass() { NullableInt = -1 }; - - db.Insert(withNull); - db.Insert(with0); - db.Insert(with1); - db.Insert(withMinus1); - - NullableIntClass[] results = db.Table().OrderBy(x => x.ID).ToArray(); - - Assert.AreEqual(4, results.Length); - - Assert.AreEqual(withNull, results[0]); - Assert.AreEqual(with0, results[1]); - Assert.AreEqual(with1, results[2]); - Assert.AreEqual(withMinus1, results[3]); - } - - - public class NullableFloatClass - { - [PrimaryKey, AutoIncrement] - public int ID { get; set; } - - public Nullable NullableFloat { get; set; } - - public override bool Equals(object obj) - { - NullableFloatClass other = (NullableFloatClass)obj; - return this.ID == other.ID && this.NullableFloat == other.NullableFloat; - } - - public override int GetHashCode () - { - return ID.GetHashCode () + NullableFloat.GetHashCode (); - } - } - - [Test] - [Description("Create a table with a nullable int column then insert and select against it")] - public void NullableFloat() - { - SQLiteConnection db = new SQLiteConnection(TestPath.GetTempFileName()); - db.CreateTable(); - - NullableFloatClass withNull = new NullableFloatClass() { NullableFloat = null }; - NullableFloatClass with0 = new NullableFloatClass() { NullableFloat = 0 }; - NullableFloatClass with1 = new NullableFloatClass() { NullableFloat = 1 }; - NullableFloatClass withMinus1 = new NullableFloatClass() { NullableFloat = -1 }; - - db.Insert(withNull); - db.Insert(with0); - db.Insert(with1); - db.Insert(withMinus1); - - NullableFloatClass[] results = db.Table().OrderBy(x => x.ID).ToArray(); - - Assert.AreEqual(4, results.Length); - - Assert.AreEqual(withNull, results[0]); - Assert.AreEqual(with0, results[1]); - Assert.AreEqual(with1, results[2]); - Assert.AreEqual(withMinus1, results[3]); - } - - - - public class StringClass - { - [PrimaryKey, AutoIncrement] - public int ID { get; set; } - - //Strings are allowed to be null by default - public string StringData { get; set; } - - public override bool Equals(object obj) - { - StringClass other = (StringClass)obj; - return this.ID == other.ID && this.StringData == other.StringData; - } - - public override int GetHashCode () - { - return ID.GetHashCode () + StringData.GetHashCode (); - } - } - - [Test] - public void NullableString() - { - SQLiteConnection db = new SQLiteConnection(TestPath.GetTempFileName()); - db.CreateTable(); - - StringClass withNull = new StringClass() { StringData = null }; - StringClass withEmpty = new StringClass() { StringData = "" }; - StringClass withData = new StringClass() { StringData = "data" }; - - db.Insert(withNull); - db.Insert(withEmpty); - db.Insert(withData); - - StringClass[] results = db.Table().OrderBy(x => x.ID).ToArray(); - - Assert.AreEqual(3, results.Length); - - Assert.AreEqual(withNull, results[0]); - Assert.AreEqual(withEmpty, results[1]); - Assert.AreEqual(withData, results[2]); - } - - [Test] - public void WhereNotNull() - { - SQLiteConnection db = new SQLiteConnection(TestPath.GetTempFileName()); - db.CreateTable(); - - NullableIntClass withNull = new NullableIntClass() { NullableInt = null }; - NullableIntClass with0 = new NullableIntClass() { NullableInt = 0 }; - NullableIntClass with1 = new NullableIntClass() { NullableInt = 1 }; - NullableIntClass withMinus1 = new NullableIntClass() { NullableInt = -1 }; - - db.Insert(withNull); - db.Insert(with0); - db.Insert(with1); - db.Insert(withMinus1); - - NullableIntClass[] results = db.Table().Where(x => x.NullableInt != null).OrderBy(x => x.ID).ToArray(); - - Assert.AreEqual(3, results.Length); - - Assert.AreEqual(with0, results[0]); - Assert.AreEqual(with1, results[1]); - Assert.AreEqual(withMinus1, results[2]); - } - - [Test] - public void WhereNull() - { - SQLiteConnection db = new SQLiteConnection(TestPath.GetTempFileName()); - db.CreateTable(); - - NullableIntClass withNull = new NullableIntClass() { NullableInt = null }; - NullableIntClass with0 = new NullableIntClass() { NullableInt = 0 }; - NullableIntClass with1 = new NullableIntClass() { NullableInt = 1 }; - NullableIntClass withMinus1 = new NullableIntClass() { NullableInt = -1 }; - - db.Insert(withNull); - db.Insert(with0); - db.Insert(with1); - db.Insert(withMinus1); - - NullableIntClass[] results = db.Table().Where(x => x.NullableInt == null).OrderBy(x => x.ID).ToArray(); - - Assert.AreEqual(1, results.Length); - Assert.AreEqual(withNull, results[0]); - } - - [Test] - public void StringWhereNull() - { - SQLiteConnection db = new SQLiteConnection(TestPath.GetTempFileName()); - db.CreateTable(); - - StringClass withNull = new StringClass() { StringData = null }; - StringClass withEmpty = new StringClass() { StringData = "" }; - StringClass withData = new StringClass() { StringData = "data" }; - - db.Insert(withNull); - db.Insert(withEmpty); - db.Insert(withData); - - StringClass[] results = db.Table().Where(x => x.StringData == null).OrderBy(x => x.ID).ToArray(); - Assert.AreEqual(1, results.Length); - Assert.AreEqual(withNull, results[0]); - } - - [Test] - public void StringWhereNotNull() - { - SQLiteConnection db = new SQLiteConnection(TestPath.GetTempFileName()); - db.CreateTable(); - - StringClass withNull = new StringClass() { StringData = null }; - StringClass withEmpty = new StringClass() { StringData = "" }; - StringClass withData = new StringClass() { StringData = "data" }; - - db.Insert(withNull); - db.Insert(withEmpty); - db.Insert(withData); - - StringClass[] results = db.Table().Where(x => x.StringData != null).OrderBy(x => x.ID).ToArray(); - Assert.AreEqual(2, results.Length); - Assert.AreEqual(withEmpty, results[0]); - Assert.AreEqual(withData, results[1]); - } - } -} + [TestFixture] + public class NullableTest + { + public class NullableIntClass + { + [PrimaryKey, AutoIncrement] + public int ID { get; set; } + + public int? NullableInt { get; set; } + + public override bool Equals(object obj) + { + var other = (NullableIntClass) obj; + return ID == other.ID && NullableInt == other.NullableInt; + } + + public override int GetHashCode() + { + return ID.GetHashCode() + NullableInt.GetHashCode(); + } + } + + + public class NullableFloatClass + { + [PrimaryKey, AutoIncrement] + public int ID { get; set; } + + public float? NullableFloat { get; set; } + + public override bool Equals(object obj) + { + var other = (NullableFloatClass) obj; + return ID == other.ID && NullableFloat == other.NullableFloat; + } + + public override int GetHashCode() + { + return ID.GetHashCode() + NullableFloat.GetHashCode(); + } + } + + + public class StringClass + { + [PrimaryKey, AutoIncrement] + public int ID { get; set; } + + //Strings are allowed to be null by default + public string StringData { get; set; } + + public override bool Equals(object obj) + { + var other = (StringClass) obj; + return ID == other.ID && StringData == other.StringData; + } + + public override int GetHashCode() + { + return ID.GetHashCode() + StringData.GetHashCode(); + } + } + + [Test] + public void NullableScalarInt() + { + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); + db.CreateTable(); + + var withNull = new NullableIntClass + { + NullableInt = null + }; + var with0 = new NullableIntClass + { + NullableInt = 0 + }; + var with1 = new NullableIntClass + { + NullableInt = 1 + }; + var withMinus1 = new NullableIntClass + { + NullableInt = -1 + }; + + db.Insert(withNull); + db.Insert(with0); + db.Insert(with1); + db.Insert(withMinus1); + + var actualShouldBeNull = db.ExecuteScalar("select NullableInt from NullableIntClass order by ID limit 1"); + var actualShouldBe0 = db.ExecuteScalar("select NullableInt from NullableIntClass order by ID limit 1 offset 1"); + var actualShouldBe1 = db.ExecuteScalar("select NullableInt from NullableIntClass order by ID limit 1 offset 2"); + var actualShouldBeMinus1 = db.ExecuteScalar("select NullableInt from NullableIntClass order by ID limit 1 offset 3"); + + Assert.AreEqual(null, actualShouldBeNull); + Assert.AreEqual(0, actualShouldBe0); + Assert.AreEqual(1, actualShouldBe1); + Assert.AreEqual(-1, actualShouldBeMinus1); + } + + [Test] + [Description("Create a table with a nullable int column then insert and select against it")] + public void NullableFloat() + { + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); + db.CreateTable(); + + var withNull = new NullableFloatClass + { + NullableFloat = null + }; + var with0 = new NullableFloatClass + { + NullableFloat = 0 + }; + var with1 = new NullableFloatClass + { + NullableFloat = 1 + }; + var withMinus1 = new NullableFloatClass + { + NullableFloat = -1 + }; + + db.Insert(withNull); + db.Insert(with0); + db.Insert(with1); + db.Insert(withMinus1); + + NullableFloatClass[] results = db.Table().OrderBy(x => x.ID).ToArray(); + + Assert.AreEqual(4, results.Length); + + Assert.AreEqual(withNull, results[0]); + Assert.AreEqual(with0, results[1]); + Assert.AreEqual(with1, results[2]); + Assert.AreEqual(withMinus1, results[3]); + } + + [Test] + [Description("Create a table with a nullable int column then insert and select against it")] + public void NullableInt() + { + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); + db.CreateTable(); + + var withNull = new NullableIntClass + { + NullableInt = null + }; + var with0 = new NullableIntClass + { + NullableInt = 0 + }; + var with1 = new NullableIntClass + { + NullableInt = 1 + }; + var withMinus1 = new NullableIntClass + { + NullableInt = -1 + }; + + db.Insert(withNull); + db.Insert(with0); + db.Insert(with1); + db.Insert(withMinus1); + + NullableIntClass[] results = db.Table().OrderBy(x => x.ID).ToArray(); + + Assert.AreEqual(4, results.Length); + + Assert.AreEqual(withNull, results[0]); + Assert.AreEqual(with0, results[1]); + Assert.AreEqual(with1, results[2]); + Assert.AreEqual(withMinus1, results[3]); + } + + [Test] + public void NullableString() + { + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); + db.CreateTable(); + + var withNull = new StringClass + { + StringData = null + }; + var withEmpty = new StringClass + { + StringData = "" + }; + var withData = new StringClass + { + StringData = "data" + }; + + db.Insert(withNull); + db.Insert(withEmpty); + db.Insert(withData); + + StringClass[] results = db.Table().OrderBy(x => x.ID).ToArray(); + + Assert.AreEqual(3, results.Length); + + Assert.AreEqual(withNull, results[0]); + Assert.AreEqual(withEmpty, results[1]); + Assert.AreEqual(withData, results[2]); + } + + [Test] + public void StringWhereNotNull() + { + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); + db.CreateTable(); + + var withNull = new StringClass + { + StringData = null + }; + var withEmpty = new StringClass + { + StringData = "" + }; + var withData = new StringClass + { + StringData = "data" + }; + + db.Insert(withNull); + db.Insert(withEmpty); + db.Insert(withData); + + StringClass[] results = + db.Table().Where(x => x.StringData != null).OrderBy(x => x.ID).ToArray(); + Assert.AreEqual(2, results.Length); + Assert.AreEqual(withEmpty, results[0]); + Assert.AreEqual(withData, results[1]); + } + + [Test] + public void StringWhereNull() + { + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); + db.CreateTable(); + + var withNull = new StringClass + { + StringData = null + }; + var withEmpty = new StringClass + { + StringData = "" + }; + var withData = new StringClass + { + StringData = "data" + }; + + db.Insert(withNull); + db.Insert(withEmpty); + db.Insert(withData); + + StringClass[] results = + db.Table().Where(x => x.StringData == null).OrderBy(x => x.ID).ToArray(); + Assert.AreEqual(1, results.Length); + Assert.AreEqual(withNull, results[0]); + } + + [Test] + public void WhereNotNull() + { + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); + db.CreateTable(); + + var withNull = new NullableIntClass + { + NullableInt = null + }; + var with0 = new NullableIntClass + { + NullableInt = 0 + }; + var with1 = new NullableIntClass + { + NullableInt = 1 + }; + var withMinus1 = new NullableIntClass + { + NullableInt = -1 + }; + + db.Insert(withNull); + db.Insert(with0); + db.Insert(with1); + db.Insert(withMinus1); + + NullableIntClass[] results = + db.Table().Where(x => x.NullableInt != null).OrderBy(x => x.ID).ToArray(); + + Assert.AreEqual(3, results.Length); + + Assert.AreEqual(with0, results[0]); + Assert.AreEqual(with1, results[1]); + Assert.AreEqual(withMinus1, results[2]); + } + + [Test] + public void WhereNull() + { + var db = new SQLiteConnection(new SQLitePlatformTest(), TestPath.GetTempFileName()); + db.CreateTable(); + + var withNull = new NullableIntClass + { + NullableInt = null + }; + var with0 = new NullableIntClass + { + NullableInt = 0 + }; + var with1 = new NullableIntClass + { + NullableInt = 1 + }; + var withMinus1 = new NullableIntClass + { + NullableInt = -1 + }; + + db.Insert(withNull); + db.Insert(with0); + db.Insert(with1); + db.Insert(withMinus1); + + NullableIntClass[] results = + db.Table().Where(x => x.NullableInt == null).OrderBy(x => x.ID).ToArray(); + + Assert.AreEqual(1, results.Length); + Assert.AreEqual(withNull, results[0]); + } + } +} \ No newline at end of file diff --git a/tests/OpenTests.cs b/tests/OpenTests.cs index e78463152..f1ddbd124 100644 --- a/tests/OpenTests.cs +++ b/tests/OpenTests.cs @@ -1,46 +1,53 @@ -using System.Linq; -using System.Text; -using SQLite; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else +using System.IO; +using System.Threading.Tasks; using NUnit.Framework; +using SQLite.Net.Async; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -using System.IO; -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class OpenTest - { - const string UnicodeText = "\u01F427 \u221E"; - - [Test] - public void UnicodePaths() - { - var path = Path.GetTempFileName () + UnicodeText; - - using (var db = new SQLiteConnection (path, true)) { - db.CreateTable (); - } - - Assert.That (new FileInfo (path).Length, Is.GreaterThan (0), path); - } - - [Test] - public void UnicodePathsAsync() - { - var path = Path.GetTempFileName () + UnicodeText; - - var db = new SQLiteAsyncConnection (path, true); - db.CreateTableAsync ().Wait (); - - Assert.That (new FileInfo (path).Length, Is.GreaterThan (0), path); - } - } -} + [TestFixture] + public class OpenTest + { + private const string UnicodeText = "\u01F427 \u221E"; + + [Test] + public void UnicodePaths() + { + string path = Path.GetTempFileName() + UnicodeText; + + using (var db = new SQLiteConnection(new SQLitePlatformTest(), path, true)) + { + db.CreateTable(); + } + + Assert.That(new FileInfo(path).Length, Is.GreaterThan(0), path); + } + + [Test] + public async Task UnicodePathsAsync() + { + string path = Path.GetTempFileName() + UnicodeText; + + var sqLiteConnectionPool = new SQLiteConnectionPool(new SQLitePlatformTest()); + var db = new SQLiteAsyncConnection(() => sqLiteConnectionPool.GetConnection(new SQLiteConnectionString(path, true))); + await db.CreateTableAsync(); + + Assert.That(new FileInfo(path).Length, Is.GreaterThan(0), path); + } + } +} \ No newline at end of file diff --git a/examples/StocksImplicit/AssemblyInfo.cs b/tests/SQLite.Net.Tests.Generic/Properties/AssemblyInfo.cs similarity index 59% rename from examples/StocksImplicit/AssemblyInfo.cs rename to tests/SQLite.Net.Tests.Generic/Properties/AssemblyInfo.cs index c415e3d57..160289386 100644 --- a/examples/StocksImplicit/AssemblyInfo.cs +++ b/tests/SQLite.Net.Tests.Generic/Properties/AssemblyInfo.cs @@ -1,26 +1,21 @@ -using System.Reflection; +using System.Reflection; using System.Runtime.CompilerServices; -// Information about this assembly is defined by the following attributes. +// Information about this assembly is defined by the following attributes. // Change them to the values specific to your project. - -[assembly: AssemblyTitle("Stocks")] -[assembly: AssemblyDescription("An example of using sqlite-net")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - +[assembly: AssemblyTitle ("SQLite.Net.Tests.Mono")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("James Ottaway")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, +[assembly: AssemblyVersion ("1.0.*")] +// The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. - //[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyKeyFile("")] diff --git a/tests/SQLite.Net.Tests.Generic/SQLite.Net.Tests.Generic.csproj b/tests/SQLite.Net.Tests.Generic/SQLite.Net.Tests.Generic.csproj new file mode 100644 index 000000000..201e25a6b --- /dev/null +++ b/tests/SQLite.Net.Tests.Generic/SQLite.Net.Tests.Generic.csproj @@ -0,0 +1,63 @@ + + + + Debug + AnyCPU + {C129735F-5D4B-40BE-9410-F43E548FFF5E} + Library + SQLite.Net.Tests.Generic + SQLite.Net.Tests.Generic + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + full + true + bin\Release + prompt + 4 + false + + + + + + + ..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll + + + + + + + + + + + packages.config + + + + + {3AB34E91-8E1A-442F-8E66-2494B371A890} + SQLite.Net.Async + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + {F662E15A-8753-468E-A67E-3FCF45F12B89} + SQLite.Net.Platform.Generic + + + diff --git a/tests/SQLite.Net.Tests.Win32/Properties/AssemblyInfo.cs b/tests/SQLite.Net.Tests.Win32/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..cadca6d6b --- /dev/null +++ b/tests/SQLite.Net.Tests.Win32/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SQLite.Net.Tests.Win32")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SQLite.Net.Tests.Win32")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9ca46ef7-2a74-4ca7-8591-b5d4855b982b")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tests/SQLite.Net.Tests.Win32/SQLite.Net.Tests.Win32.csproj b/tests/SQLite.Net.Tests.Win32/SQLite.Net.Tests.Win32.csproj new file mode 100644 index 000000000..1c123b10e --- /dev/null +++ b/tests/SQLite.Net.Tests.Win32/SQLite.Net.Tests.Win32.csproj @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + {BFF4B373-2844-40AD-8994-2BA5AC42AEE0} + Library + Properties + SQLite.Net.Tests.Win32 + SQLite.Net.Tests.Win32 + v4.5 + 512 + ..\..\ + true + 12.0.0 + 2.0 + + + true + full + false + bin\Debug\ + TRACE;DEBUG;__WIN32__ + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;__WIN32__ + prompt + 4 + + + + ..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll + + + + + + + + + + + + + + + + {3AB34E91-8E1A-442F-8E66-2494B371A890} + SQLite.Net.Async + + + {03799AD1-9FCF-48CB-8E6E-B233DF583B10} + SQLite.Net.Platform.Win32 + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.Win32/packages.config b/tests/SQLite.Net.Tests.Win32/packages.config new file mode 100644 index 000000000..ad37a5282 --- /dev/null +++ b/tests/SQLite.Net.Tests.Win32/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tests/SQLiteMetroTests/Images/UnitTestLogo.png b/tests/SQLite.Net.Tests.WinRT/Images/UnitTestLogo.scale-100.png similarity index 100% rename from tests/SQLiteMetroTests/Images/UnitTestLogo.png rename to tests/SQLite.Net.Tests.WinRT/Images/UnitTestLogo.scale-100.png diff --git a/tests/SQLiteMetroTests/Images/UnitTestSmallLogo.png b/tests/SQLite.Net.Tests.WinRT/Images/UnitTestSmallLogo.scale-100.png similarity index 100% rename from tests/SQLiteMetroTests/Images/UnitTestSmallLogo.png rename to tests/SQLite.Net.Tests.WinRT/Images/UnitTestSmallLogo.scale-100.png diff --git a/tests/SQLiteMetroTests/Images/UnitTestSplashScreen.png b/tests/SQLite.Net.Tests.WinRT/Images/UnitTestSplashScreen.scale-100.png similarity index 100% rename from tests/SQLiteMetroTests/Images/UnitTestSplashScreen.png rename to tests/SQLite.Net.Tests.WinRT/Images/UnitTestSplashScreen.scale-100.png diff --git a/tests/SQLiteMetroTests/Images/UnitTestStoreLogo.png b/tests/SQLite.Net.Tests.WinRT/Images/UnitTestStoreLogo.scale-100.png similarity index 100% rename from tests/SQLiteMetroTests/Images/UnitTestStoreLogo.png rename to tests/SQLite.Net.Tests.WinRT/Images/UnitTestStoreLogo.scale-100.png diff --git a/tests/SQLiteMetroTests/Package.appxmanifest b/tests/SQLite.Net.Tests.WinRT/Package.appxmanifest similarity index 78% rename from tests/SQLiteMetroTests/Package.appxmanifest rename to tests/SQLite.Net.Tests.WinRT/Package.appxmanifest index 22b9b8a00..e78788c77 100644 --- a/tests/SQLiteMetroTests/Package.appxmanifest +++ b/tests/SQLite.Net.Tests.WinRT/Package.appxmanifest @@ -1,20 +1,20 @@  - - SQLiteMetroTests - Frank + SQLite.Net.Tests.WinRT + Øystein Images\UnitTestStoreLogo.png - SQLiteMetroTests + SQLite.Net.Tests.WinRT - 6.2 - 6.2 + 6.3.0 + 6.3.0 @@ -50,5 +50,7 @@ - + + + diff --git a/tests/SQLiteMetroTests/Properties/AssemblyInfo.cs b/tests/SQLite.Net.Tests.WinRT/Properties/AssemblyInfo.cs similarity index 81% rename from tests/SQLiteMetroTests/Properties/AssemblyInfo.cs rename to tests/SQLite.Net.Tests.WinRT/Properties/AssemblyInfo.cs index 00fc7ffc7..94b1348c9 100644 --- a/tests/SQLiteMetroTests/Properties/AssemblyInfo.cs +++ b/tests/SQLite.Net.Tests.WinRT/Properties/AssemblyInfo.cs @@ -5,12 +5,12 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("SQLiteMetroTests")] +[assembly: AssemblyTitle("SQLite.Net.Tests.WinRT")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("SQLiteMetroTests")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2012")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SQLite.Net.Tests.WinRT")] +[assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/tests/SQLite.Net.Tests.WinRT/SQLite.Net.Tests.WinRT.csproj b/tests/SQLite.Net.Tests.WinRT/SQLite.Net.Tests.WinRT.csproj new file mode 100644 index 000000000..aacb5a03e --- /dev/null +++ b/tests/SQLite.Net.Tests.WinRT/SQLite.Net.Tests.WinRT.csproj @@ -0,0 +1,282 @@ + + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {5BB50827-ECC8-4BCD-9AFD-DCCA71F6D753} + Library + Properties + SQLite.Net.Tests.WinRT + SQLite.Net.Tests.WinRT + en-US + 8.1 + 12 + 512 + {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + SQLite.Net.Tests.WinRT_TemporaryKey.pfx + Never + ..\..\ + true + + + true + full + false + bin\Debug\ + TRACE;DEBUG;__WINRT__ + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;__WINRT__ + prompt + 4 + + + true + bin\ARM\Debug\ + TRACE;DEBUG;__WINRT__ + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;__WINRT__ + true + ;2008 + pdbonly + ARM + false + prompt + true + + + true + bin\x64\Debug\ + TRACE;DEBUG;__WINRT__ + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + TRACE;__WINRT__ + true + ;2008 + pdbonly + x64 + false + prompt + true + + + true + bin\x86\Debug\ + TRACE;DEBUG;__WINRT__ + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;__WINRT__ + true + ;2008 + pdbonly + x86 + false + prompt + true + + + True + true + + + + + + + + Tests\AsyncTests.cs + + + Tests\BlobSerializationTest.cs + + + Tests\BooleanTest.cs + + + Tests\ByteArrayTest.cs + + + Tests\CollateTest.cs + + + Tests\ConnectionTrackingTest.cs + + + Tests\ContainsTest.cs + + + Tests\CreateTableImplicitTest.cs + + + Tests\CreateTableTest.cs + + + Tests\DateTimeTest.cs + + + Tests\DeleteTest.cs + + + Tests\DropTableTest.cs + + + Tests\EqualsTest.cs + + + Tests\ExceptionAssert.cs + + + Tests\ExpressionTests.cs + + + Tests\GuidTests.cs + + + Tests\InheritanceTest.cs + + + Tests\InsertTest.cs + + + Tests\JoinTest.cs + + + Tests\LinqTest.cs + + + Tests\MappingTest.cs + + + Tests\MigrationTest.cs + + + NotNullAttributeTest.cs + + + Tests\NullableTest.cs + + + Tests\OpenTests.cs + + + Tests\ScalarTest.cs + + + Tests\SkipTest.cs + + + Tests\StringQueryTest.cs + + + Tests\TestDb.cs + + + Tests\TimeSpanTest.cs + + + Tests\TransactionTest.cs + + + Tests\UnicodeTest.cs + + + Tests\UniqueTest.cs + + + Tests\SerializableTest.cs + + + + + + + Designer + + + Tests\packages.config + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + ..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll + + + + + {3ab34e91-8e1a-442f-8e66-2494b371a890} + SQLite.Net.Async + + + {6891e212-aeee-4763-ac6f-bd7213c13890} + SQLite.Net.Platform.WinRT + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + + 12.0 + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.WinRT/SQLite.Net.Tests.WinRT_TemporaryKey.pfx b/tests/SQLite.Net.Tests.WinRT/SQLite.Net.Tests.WinRT_TemporaryKey.pfx new file mode 100644 index 000000000..297c68ff8 Binary files /dev/null and b/tests/SQLite.Net.Tests.WinRT/SQLite.Net.Tests.WinRT_TemporaryKey.pfx differ diff --git a/tests/SQLite.Net.Tests.WinRT/packages.config b/tests/SQLite.Net.Tests.WinRT/packages.config new file mode 100644 index 000000000..900373163 --- /dev/null +++ b/tests/SQLite.Net.Tests.WinRT/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/App.xaml b/tests/SQLite.Net.Tests.WindowsPhone8/App.xaml new file mode 100644 index 000000000..9edd31f4b --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/App.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/App.xaml.cs b/tests/SQLite.Net.Tests.WindowsPhone8/App.xaml.cs new file mode 100644 index 000000000..b238348e2 --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/App.xaml.cs @@ -0,0 +1,223 @@ +using System; +using System.Diagnostics; +using System.Resources; +using System.Windows; +using System.Windows.Markup; +using System.Windows.Navigation; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; +using SQLite.Net.Tests.WindowsPhone8.Resources; + +namespace SQLite.Net.Tests.WindowsPhone8 +{ + public partial class App : Application + { + /// + /// Provides easy access to the root frame of the Phone Application. + /// + /// The root frame of the Phone Application. + public static PhoneApplicationFrame RootFrame { get; private set; } + + /// + /// Constructor for the Application object. + /// + public App() + { + // Global handler for uncaught exceptions. + UnhandledException += Application_UnhandledException; + + // Standard XAML initialization + InitializeComponent(); + + // Phone-specific initialization + InitializePhoneApplication(); + + // Language display initialization + InitializeLanguage(); + + // Show graphics profiling information while debugging. + if (Debugger.IsAttached) + { + // Display the current frame rate counters. + Application.Current.Host.Settings.EnableFrameRateCounter = true; + + // Show the areas of the app that are being redrawn in each frame. + //Application.Current.Host.Settings.EnableRedrawRegions = true; + + // Enable non-production analysis visualization mode, + // which shows areas of a page that are handed off to GPU with a colored overlay. + //Application.Current.Host.Settings.EnableCacheVisualization = true; + + // Prevent the screen from turning off while under the debugger by disabling + // the application's idle detection. + // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run + // and consume battery power when the user is not using the phone. + PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled; + } + + } + + // Code to execute when the application is launching (eg, from Start) + // This code will not execute when the application is reactivated + private void Application_Launching(object sender, LaunchingEventArgs e) + { + } + + // Code to execute when the application is activated (brought to foreground) + // This code will not execute when the application is first launched + private void Application_Activated(object sender, ActivatedEventArgs e) + { + } + + // Code to execute when the application is deactivated (sent to background) + // This code will not execute when the application is closing + private void Application_Deactivated(object sender, DeactivatedEventArgs e) + { + } + + // Code to execute when the application is closing (eg, user hit Back) + // This code will not execute when the application is deactivated + private void Application_Closing(object sender, ClosingEventArgs e) + { + } + + // Code to execute if a navigation fails + private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e) + { + if (Debugger.IsAttached) + { + // A navigation has failed; break into the debugger + Debugger.Break(); + } + } + + // Code to execute on Unhandled Exceptions + private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) + { + if (Debugger.IsAttached) + { + // An unhandled exception has occurred; break into the debugger + Debugger.Break(); + } + } + + #region Phone application initialization + + // Avoid double-initialization + private bool phoneApplicationInitialized = false; + + // Do not add any additional code to this method + private void InitializePhoneApplication() + { + if (phoneApplicationInitialized) + return; + + // Create the frame but don't set it as RootVisual yet; this allows the splash + // screen to remain active until the application is ready to render. + RootFrame = new PhoneApplicationFrame(); + RootFrame.Navigated += CompleteInitializePhoneApplication; + + // Handle navigation failures + RootFrame.NavigationFailed += RootFrame_NavigationFailed; + + // Handle reset requests for clearing the backstack + RootFrame.Navigated += CheckForResetNavigation; + + // Ensure we don't initialize again + phoneApplicationInitialized = true; + } + + // Do not add any additional code to this method + private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e) + { + // Set the root visual to allow the application to render + if (RootVisual != RootFrame) + RootVisual = RootFrame; + + // Remove this handler since it is no longer needed + RootFrame.Navigated -= CompleteInitializePhoneApplication; + } + + private void CheckForResetNavigation(object sender, NavigationEventArgs e) + { + // If the app has received a 'reset' navigation, then we need to check + // on the next navigation to see if the page stack should be reset + if (e.NavigationMode == NavigationMode.Reset) + RootFrame.Navigated += ClearBackStackAfterReset; + } + + private void ClearBackStackAfterReset(object sender, NavigationEventArgs e) + { + // Unregister the event so it doesn't get called again + RootFrame.Navigated -= ClearBackStackAfterReset; + + // Only clear the stack for 'new' (forward) and 'refresh' navigations + if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh) + return; + + // For UI consistency, clear the entire page stack + while (RootFrame.RemoveBackEntry() != null) + { + ; // do nothing + } + } + + #endregion + + // Initialize the app's font and flow direction as defined in its localized resource strings. + // + // To ensure that the font of your application is aligned with its supported languages and that the + // FlowDirection for each of those languages follows its traditional direction, ResourceLanguage + // and ResourceFlowDirection should be initialized in each resx file to match these values with that + // file's culture. For example: + // + // AppResources.es-ES.resx + // ResourceLanguage's value should be "es-ES" + // ResourceFlowDirection's value should be "LeftToRight" + // + // AppResources.ar-SA.resx + // ResourceLanguage's value should be "ar-SA" + // ResourceFlowDirection's value should be "RightToLeft" + // + // For more info on localizing Windows Phone apps see http://go.microsoft.com/fwlink/?LinkId=262072. + // + private void InitializeLanguage() + { + try + { + // Set the font to match the display language defined by the + // ResourceLanguage resource string for each supported language. + // + // Fall back to the font of the neutral language if the Display + // language of the phone is not supported. + // + // If a compiler error is hit then ResourceLanguage is missing from + // the resource file. + RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage); + + // Set the FlowDirection of all elements under the root frame based + // on the ResourceFlowDirection resource string for each + // supported language. + // + // If a compiler error is hit then ResourceFlowDirection is missing from + // the resource file. + FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection); + RootFrame.FlowDirection = flow; + } + catch + { + // If an exception is caught here it is most likely due to either + // ResourceLangauge not being correctly set to a supported language + // code or ResourceFlowDirection is set to a value other than LeftToRight + // or RightToLeft. + + if (Debugger.IsAttached) + { + Debugger.Break(); + } + + throw; + } + } + } +} \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/Assets/AlignmentGrid.png b/tests/SQLite.Net.Tests.WindowsPhone8/Assets/AlignmentGrid.png new file mode 100644 index 000000000..f7d2e9780 Binary files /dev/null and b/tests/SQLite.Net.Tests.WindowsPhone8/Assets/AlignmentGrid.png differ diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/Assets/ApplicationIcon.png b/tests/SQLite.Net.Tests.WindowsPhone8/Assets/ApplicationIcon.png new file mode 100644 index 000000000..7d95d4e08 Binary files /dev/null and b/tests/SQLite.Net.Tests.WindowsPhone8/Assets/ApplicationIcon.png differ diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/Assets/Tiles/FlipCycleTileLarge.png b/tests/SQLite.Net.Tests.WindowsPhone8/Assets/Tiles/FlipCycleTileLarge.png new file mode 100644 index 000000000..e0c59ac01 Binary files /dev/null and b/tests/SQLite.Net.Tests.WindowsPhone8/Assets/Tiles/FlipCycleTileLarge.png differ diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/Assets/Tiles/FlipCycleTileMedium.png b/tests/SQLite.Net.Tests.WindowsPhone8/Assets/Tiles/FlipCycleTileMedium.png new file mode 100644 index 000000000..e93b89d60 Binary files /dev/null and b/tests/SQLite.Net.Tests.WindowsPhone8/Assets/Tiles/FlipCycleTileMedium.png differ diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/Assets/Tiles/FlipCycleTileSmall.png b/tests/SQLite.Net.Tests.WindowsPhone8/Assets/Tiles/FlipCycleTileSmall.png new file mode 100644 index 000000000..550b1b5e8 Binary files /dev/null and b/tests/SQLite.Net.Tests.WindowsPhone8/Assets/Tiles/FlipCycleTileSmall.png differ diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/LocalizedStrings.cs b/tests/SQLite.Net.Tests.WindowsPhone8/LocalizedStrings.cs new file mode 100644 index 000000000..224f18a51 --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/LocalizedStrings.cs @@ -0,0 +1,14 @@ +using SQLite.Net.Tests.WindowsPhone8.Resources; + +namespace SQLite.Net.Tests.WindowsPhone8 +{ + /// + /// Provides access to string resources. + /// + public class LocalizedStrings + { + private static AppResources _localizedResources = new AppResources(); + + public AppResources LocalizedResources { get { return _localizedResources; } } + } +} \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/MainPage.xaml b/tests/SQLite.Net.Tests.WindowsPhone8/MainPage.xaml new file mode 100644 index 000000000..bd22d66b4 --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/MainPage.xaml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/MainPage.xaml.cs b/tests/SQLite.Net.Tests.WindowsPhone8/MainPage.xaml.cs new file mode 100644 index 000000000..6763bb69b --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/MainPage.xaml.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Navigation; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; +using SQLite.Net.Tests.WindowsPhone8.Resources; +using System.Threading; +using Microsoft.VisualStudio.TestPlatform.Core; +using vstest_executionengine_platformbridge; +using Microsoft.VisualStudio.TestPlatform.TestExecutor; +using System.Reflection; + +namespace SQLite.Net.Tests.WindowsPhone8 +{ + public partial class MainPage : PhoneApplicationPage + { + // Constructor + public MainPage() + { + InitializeComponent(); + + var wrapper = new TestExecutorServiceWrapper(); + new Thread(new ServiceMain((param0, param1) => wrapper.SendMessage((ContractName)param0, param1)).Run).Start(); + + } + } +} \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/Properties/AppManifest.xml b/tests/SQLite.Net.Tests.WindowsPhone8/Properties/AppManifest.xml new file mode 100644 index 000000000..6712a1178 --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/Properties/AppManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/Properties/AssemblyInfo.cs b/tests/SQLite.Net.Tests.WindowsPhone8/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..ec3a06764 --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SQLite.Net.Tests.WindowsPhone8")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SQLite.Net.Tests.WindowsPhone8")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("d45b5167-efa6-496a-92cb-975438814621")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/Properties/WMAppManifest.xml b/tests/SQLite.Net.Tests.WindowsPhone8/Properties/WMAppManifest.xml new file mode 100644 index 000000000..054d72bf1 --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/Properties/WMAppManifest.xml @@ -0,0 +1,46 @@ + + + + + + Assets\ApplicationIcon.png + + + + + + + + + + + + + + Assets\Tiles\FlipCycleTileSmall.png + 0 + Assets\Tiles\FlipCycleTileMedium.png + SQLite.Net.Tests.WindowsPhone8 + + + + + + + + + + + vstest_executionengine_platformbridge.dll + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/Resources/AppResources.Designer.cs b/tests/SQLite.Net.Tests.WindowsPhone8/Resources/AppResources.Designer.cs new file mode 100644 index 000000000..ac7234995 --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/Resources/AppResources.Designer.cs @@ -0,0 +1,127 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.17626 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SQLite.Net.Tests.WindowsPhone8.Resources +{ + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class AppResources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal AppResources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager + { + get + { + if (object.ReferenceEquals(resourceMan, null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SQLite.Net.Tests.WindowsPhone8.Resources.AppResources", typeof(AppResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to LeftToRight. + /// + public static string ResourceFlowDirection + { + get + { + return ResourceManager.GetString("ResourceFlowDirection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to us-EN. + /// + public static string ResourceLanguage + { + get + { + return ResourceManager.GetString("ResourceLanguage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MY APPLICATION. + /// + public static string ApplicationTitle + { + get + { + return ResourceManager.GetString("ApplicationTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to button. + /// + public static string AppBarButtonText + { + get + { + return ResourceManager.GetString("AppBarButtonText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to menu item. + /// + public static string AppBarMenuItemText + { + get + { + return ResourceManager.GetString("AppBarMenuItemText", resourceCulture); + } + } + } +} diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/Resources/AppResources.resx b/tests/SQLite.Net.Tests.WindowsPhone8/Resources/AppResources.resx new file mode 100644 index 000000000..529a19431 --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/Resources/AppResources.resx @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + LeftToRight + Controls the FlowDirection for all elements in the RootFrame. Set to the traditional direction of this resource file's language + + + en-US + Controls the Language and ensures that the font for all elements in the RootFrame aligns with the app's language. Set to the language code of this resource file's language. + + + MY APPLICATION + + + add + + + Menu Item + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/SQLite.Net.Tests.WindowsPhone8.csproj b/tests/SQLite.Net.Tests.WindowsPhone8/SQLite.Net.Tests.WindowsPhone8.csproj new file mode 100644 index 000000000..b674473ab --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/SQLite.Net.Tests.WindowsPhone8.csproj @@ -0,0 +1,169 @@ + + + + Debug + x86 + 10.0.20506 + 2.0 + {46DF3E43-6B65-4C3D-8911-64FCC301040F} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + SQLite.Net.Tests.WindowsPhone8 + SQLite.Net.Tests.WindowsPhone8 + WindowsPhone + v8.0 + $(TargetFrameworkVersion) + true + true + + + true + true + SQLite.Net.Tests.WindowsPhone8_$(Configuration)_$(Platform).xap + Properties\AppManifest.xml + SQLite.Net.Tests.WindowsPhone8.App + false + 11.0 + true + ..\..\ + true + + + true + full + false + Bin\x86\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\ARM\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + + App.xaml + + + + MainPage.xaml + + + + True + True + AppResources.resx + + + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + + + Designer + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + PublicResXFileCodeGenerator + AppResources.Designer.cs + + + + + {3AB34E91-8E1A-442F-8E66-2494B371A890} + SQLite.Net.Async + + + {741521F8-F9D8-40F4-A5D4-AED4E26841ED} + SQLite.Net.Platform.WindowsPhone8 + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + + + ..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.WindowsPhone8/packages.config b/tests/SQLite.Net.Tests.WindowsPhone8/packages.config new file mode 100644 index 000000000..4f4299df7 --- /dev/null +++ b/tests/SQLite.Net.Tests.WindowsPhone8/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.XamarinAndroid/Assets/AboutAssets.txt b/tests/SQLite.Net.Tests.XamarinAndroid/Assets/AboutAssets.txt new file mode 100644 index 000000000..a9b0638eb --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinAndroid/Assets/AboutAssets.txt @@ -0,0 +1,19 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories) and given a Build Action of "AndroidAsset". + +These files will be deployed with your package and will be accessible using Android's +AssetManager, like this: + +public class ReadAsset : Activity +{ + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + InputStream input = Assets.Open ("my_asset.txt"); + } +} + +Additionally, some Android functions will automatically load asset files: + +Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); diff --git a/tests/SQLite.Net.Tests.XamarinAndroid/MainActivity.cs b/tests/SQLite.Net.Tests.XamarinAndroid/MainActivity.cs new file mode 100644 index 000000000..4b76832f9 --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinAndroid/MainActivity.cs @@ -0,0 +1,23 @@ +using System.Reflection; +using Android.App; +using Android.OS; +using Xamarin.Android.NUnitLite; + +namespace SQLite.Net.Tests.XamarinAndroid +{ + [Activity (Label = "SQLite.Net.Tests.XamarinAndroid", MainLauncher = true)] + public class MainActivity : TestSuiteActivity + { + protected override void OnCreate (Bundle bundle) + { + // tests can be inside the main assembly + AddTest (Assembly.GetExecutingAssembly ()); + // or in any reference assemblies + // AddTest (typeof (Your.Library.TestClass).Assembly); + + // Once you called base.OnCreate(), you cannot add more assemblies. + base.OnCreate (bundle); + } + } +} + diff --git a/tests/SQLite.Net.Tests.XamarinAndroid/Properties/AndroidManifest.xml b/tests/SQLite.Net.Tests.XamarinAndroid/Properties/AndroidManifest.xml new file mode 100644 index 000000000..c074f195f --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinAndroid/Properties/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.XamarinAndroid/Properties/AssemblyInfo.cs b/tests/SQLite.Net.Tests.XamarinAndroid/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..3678e1cb1 --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinAndroid/Properties/AssemblyInfo.cs @@ -0,0 +1,23 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using Android.App; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. +[assembly: AssemblyTitle ("SQLite.Net.Tests.XamarinAndroid")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("Øystein")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. +[assembly: AssemblyVersion ("1.0.0")] +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/tests/SQLite.Net.Tests.XamarinAndroid/Resources/AboutResources.txt b/tests/SQLite.Net.Tests.XamarinAndroid/Resources/AboutResources.txt new file mode 100644 index 000000000..10f52d460 --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinAndroid/Resources/AboutResources.txt @@ -0,0 +1,44 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. diff --git a/tests/SQLite.Net.Tests.XamarinAndroid/Resources/Resource.designer.cs b/tests/SQLite.Net.Tests.XamarinAndroid/Resources/Resource.designer.cs new file mode 100644 index 000000000..28ae159c8 --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinAndroid/Resources/Resource.designer.cs @@ -0,0 +1,196 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("SQLite.Net.Tests.XamarinAndroid.Resource", IsApplication=true)] + +namespace SQLite.Net.Tests.XamarinAndroid +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public static void UpdateIdValues() + { + global::SQLite.Net.Platform.XamarinAndroid.Resource.String.ApplicationName = global::SQLite.Net.Tests.XamarinAndroid.Resource.String.ApplicationName; + global::SQLite.Net.Platform.XamarinAndroid.Resource.String.Hello = global::SQLite.Net.Tests.XamarinAndroid.Resource.String.Hello; + global::Xamarin.Android.NUnitLite.Resource.Id.OptionHostName = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.OptionHostName; + global::Xamarin.Android.NUnitLite.Resource.Id.OptionPort = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.OptionPort; + global::Xamarin.Android.NUnitLite.Resource.Id.OptionRemoteServer = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.OptionRemoteServer; + global::Xamarin.Android.NUnitLite.Resource.Id.OptionsButton = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.OptionsButton; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultFullName = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultFullName; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultMessage = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultMessage; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultResultState = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultResultState; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultRunSingleMethodTest = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultRunSingleMethodTest; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultStackTrace = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultStackTrace; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsFailed = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultsFailed; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsId = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultsId; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsIgnored = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultsIgnored; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsInconclusive = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultsInconclusive; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsMessage = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultsMessage; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsPassed = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultsPassed; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsResult = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.ResultsResult; + global::Xamarin.Android.NUnitLite.Resource.Id.RunTestsButton = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.RunTestsButton; + global::Xamarin.Android.NUnitLite.Resource.Id.TestSuiteListView = global::SQLite.Net.Tests.XamarinAndroid.Resource.Id.TestSuiteListView; + global::Xamarin.Android.NUnitLite.Resource.Layout.options = global::SQLite.Net.Tests.XamarinAndroid.Resource.Layout.options; + global::Xamarin.Android.NUnitLite.Resource.Layout.results = global::SQLite.Net.Tests.XamarinAndroid.Resource.Layout.results; + global::Xamarin.Android.NUnitLite.Resource.Layout.test_result = global::SQLite.Net.Tests.XamarinAndroid.Resource.Layout.test_result; + global::Xamarin.Android.NUnitLite.Resource.Layout.test_suite = global::SQLite.Net.Tests.XamarinAndroid.Resource.Layout.test_suite; + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Drawable + { + + // aapt resource value: 0x7f020000 + public const int Icon = 2130837504; + + static Drawable() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Drawable() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7f050001 + public const int OptionHostName = 2131034113; + + // aapt resource value: 0x7f050002 + public const int OptionPort = 2131034114; + + // aapt resource value: 0x7f050000 + public const int OptionRemoteServer = 2131034112; + + // aapt resource value: 0x7f050010 + public const int OptionsButton = 2131034128; + + // aapt resource value: 0x7f05000b + public const int ResultFullName = 2131034123; + + // aapt resource value: 0x7f05000d + public const int ResultMessage = 2131034125; + + // aapt resource value: 0x7f05000c + public const int ResultResultState = 2131034124; + + // aapt resource value: 0x7f05000a + public const int ResultRunSingleMethodTest = 2131034122; + + // aapt resource value: 0x7f05000e + public const int ResultStackTrace = 2131034126; + + // aapt resource value: 0x7f050006 + public const int ResultsFailed = 2131034118; + + // aapt resource value: 0x7f050003 + public const int ResultsId = 2131034115; + + // aapt resource value: 0x7f050007 + public const int ResultsIgnored = 2131034119; + + // aapt resource value: 0x7f050008 + public const int ResultsInconclusive = 2131034120; + + // aapt resource value: 0x7f050009 + public const int ResultsMessage = 2131034121; + + // aapt resource value: 0x7f050005 + public const int ResultsPassed = 2131034117; + + // aapt resource value: 0x7f050004 + public const int ResultsResult = 2131034116; + + // aapt resource value: 0x7f05000f + public const int RunTestsButton = 2131034127; + + // aapt resource value: 0x7f050011 + public const int TestSuiteListView = 2131034129; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7f030000 + public const int options = 2130903040; + + // aapt resource value: 0x7f030001 + public const int results = 2130903041; + + // aapt resource value: 0x7f030002 + public const int test_result = 2130903042; + + // aapt resource value: 0x7f030003 + public const int test_suite = 2130903043; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f040001 + public const int ApplicationName = 2130968577; + + // aapt resource value: 0x7f040000 + public const int Hello = 2130968576; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/tests/SQLite.Net.Tests.XamarinAndroid/Resources/drawable/Icon.png b/tests/SQLite.Net.Tests.XamarinAndroid/Resources/drawable/Icon.png new file mode 100644 index 000000000..a07c69fa5 Binary files /dev/null and b/tests/SQLite.Net.Tests.XamarinAndroid/Resources/drawable/Icon.png differ diff --git a/tests/SQLite.Net.Tests.XamarinAndroid/SQLite.Net.Tests.XamarinAndroid.csproj b/tests/SQLite.Net.Tests.XamarinAndroid/SQLite.Net.Tests.XamarinAndroid.csproj new file mode 100644 index 000000000..a5b662563 --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinAndroid/SQLite.Net.Tests.XamarinAndroid.csproj @@ -0,0 +1,85 @@ + + + + Debug + AnyCPU + 12.0.0 + 2.0 + {2C3224FB-4513-4A16-B67F-3C4F1BDC7765} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + SQLite.Net.Tests.XamarinAndroid + Resources + Assets + True + True + Resources\Resource.designer.cs + Resource + SQLite.Net.Tests.XamarinAndroid + v4.0.3 + Properties\AndroidManifest.xml + + + true + full + false + bin\Debug + DEBUG;__MOBILE__;__ANDROID__; + prompt + 4 + None + false + + + full + true + bin\Release + __MOBILE__;__ANDROID__; + prompt + 4 + false + false + + + + + + + + + + + + + + + + + + Tests\packages.config + + + + + + + + + + + + + {3AB34E91-8E1A-442F-8E66-2494B371A890} + SQLite.Net.Async + + + {219700f0-5444-4250-87d6-0551b39ca402} + SQLite.Net.Platform.XamarinAndroid + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.XamarinAndroid/TestsSample.cs b/tests/SQLite.Net.Tests.XamarinAndroid/TestsSample.cs new file mode 100644 index 000000000..734b3dd09 --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinAndroid/TestsSample.cs @@ -0,0 +1,46 @@ +using System; +using NUnit.Framework; + +namespace SQLite.Net.Tests.XamarinAndroid +{ + [TestFixture] + public class TestsSample + { + [SetUp] + public void Setup () + { + } + + [TearDown] + public void Tear () + { + } + + [Test] + public void Pass () + { + Console.WriteLine ("test1"); + Assert.True (true); + } + + [Test] + public void Fail () + { + Assert.False (true); + } + + [Test] + [Ignore ("another time")] + public void Ignore () + { + Assert.True (false); + } + + [Test] + public void Inconclusive () + { + Assert.Inconclusive ("Inconclusive"); + } + } +} + diff --git a/tests/SQLiteTouchTests/AppDelegate.cs b/tests/SQLite.Net.Tests.XamarinIOS.Unified/AppDelegate.cs similarity index 63% rename from tests/SQLiteTouchTests/AppDelegate.cs rename to tests/SQLite.Net.Tests.XamarinIOS.Unified/AppDelegate.cs index d10cbd079..7eadd1071 100644 --- a/tests/SQLiteTouchTests/AppDelegate.cs +++ b/tests/SQLite.Net.Tests.XamarinIOS.Unified/AppDelegate.cs @@ -1,15 +1,15 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; -using MonoTouch.Foundation; -using MonoTouch.UIKit; +using Foundation; +using UIKit; using MonoTouch.NUnit.UI; -namespace SQLiteTouchTests +namespace SQLite.Net.Tests.XamarinIOS.Unified { - // The UIApplicationDelegate for the application. This class is responsible for launching the - // User Interface of the application, as well as listening (and optionally responding) to + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to // application events from iOS. [Register ("AppDelegate")] public partial class AppDelegate : UIApplicationDelegate @@ -19,7 +19,7 @@ public partial class AppDelegate : UIApplicationDelegate TouchRunner runner; // - // This method is invoked when the application has loaded and is ready to run. In this + // This method is invoked when the application has loaded and is ready to run. In this // method you should instantiate the window, load the UI into it and then make the window // visible. // @@ -27,17 +27,16 @@ public partial class AppDelegate : UIApplicationDelegate // public override bool FinishedLaunching (UIApplication app, NSDictionary options) { - // create a new window instance based on the screen size - window = new UIWindow (UIScreen.MainScreen.Bounds); - runner = new TouchRunner (window); + window = new UIWindow(UIScreen.MainScreen.Bounds); + runner = new TouchRunner(window); // register every tests included in the main application/assembly - runner.Add (System.Reflection.Assembly.GetExecutingAssembly ()); + runner.Add(System.Reflection.Assembly.GetExecutingAssembly()); + + window.RootViewController = new UINavigationController(runner.GetViewController()); - window.RootViewController = new UINavigationController (runner.GetViewController ()); - // make the window visible - window.MakeKeyAndVisible (); + window.MakeKeyAndVisible(); return true; } diff --git a/tests/SQLiteTouchTests/Info.plist b/tests/SQLite.Net.Tests.XamarinIOS.Unified/Info.plist similarity index 63% rename from tests/SQLiteTouchTests/Info.plist rename to tests/SQLite.Net.Tests.XamarinIOS.Unified/Info.plist index 8653860cf..38aeb2426 100644 --- a/tests/SQLiteTouchTests/Info.plist +++ b/tests/SQLite.Net.Tests.XamarinIOS.Unified/Info.plist @@ -2,11 +2,25 @@ + CFBundleDisplayName + SQLite.Net.Tests.XamarinIOS.Unified + CFBundleIdentifier + SQLite.Net.Tests.XamarinIOS.Unified + LSRequiresIPhoneOS + + MinimumOSVersion + 6.0 UIDeviceFamily 1 2 + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + UISupportedInterfaceOrientations UIInterfaceOrientationPortrait @@ -20,7 +34,7 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - MinimumOSVersion - 3.2 + XSAppIconAssets + Resources/Images.xcassets/AppIcons.appiconset diff --git a/tests/SQLiteTouchTests/Main.cs b/tests/SQLite.Net.Tests.XamarinIOS.Unified/Main.cs similarity index 78% rename from tests/SQLiteTouchTests/Main.cs rename to tests/SQLite.Net.Tests.XamarinIOS.Unified/Main.cs index 661d3b578..4e5e7c56a 100644 --- a/tests/SQLiteTouchTests/Main.cs +++ b/tests/SQLite.Net.Tests.XamarinIOS.Unified/Main.cs @@ -1,11 +1,11 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; -using MonoTouch.Foundation; -using MonoTouch.UIKit; +using Foundation; +using UIKit; -namespace SQLiteTouchTests +namespace SQLite.Net.Tests.XamarinIOS.Unified { public class Application { diff --git a/tests/SQLite.Net.Tests.XamarinIOS.Unified/Resources/Images.xcassets/AppIcons.appiconset/Contents.json b/tests/SQLite.Net.Tests.XamarinIOS.Unified/Resources/Images.xcassets/AppIcons.appiconset/Contents.json new file mode 100644 index 000000000..24f997458 --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinIOS.Unified/Resources/Images.xcassets/AppIcons.appiconset/Contents.json @@ -0,0 +1,108 @@ +{ + "images": [ + { + "size": "29x29", + "scale": "1x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "3x", + "idiom": "iphone" + }, + { + "size": "40x40", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "40x40", + "scale": "3x", + "idiom": "iphone" + }, + { + "size": "57x57", + "scale": "1x", + "idiom": "iphone" + }, + { + "size": "57x57", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "60x60", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "60x60", + "scale": "3x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "29x29", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "40x40", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "40x40", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "50x50", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "50x50", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "72x72", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "72x72", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "76x76", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "76x76", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "120x120", + "scale": "1x", + "idiom": "car" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.XamarinIOS.Unified/Resources/LaunchScreen.xib b/tests/SQLite.Net.Tests.XamarinIOS.Unified/Resources/LaunchScreen.xib new file mode 100644 index 000000000..8fe343cfd --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinIOS.Unified/Resources/LaunchScreen.xib @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SQLiteTouchTests/SQLiteTouchTests.csproj b/tests/SQLite.Net.Tests.XamarinIOS.Unified/SQLite.Net.Tests.XamarinIOS.Unified.csproj similarity index 53% rename from tests/SQLiteTouchTests/SQLiteTouchTests.csproj rename to tests/SQLite.Net.Tests.XamarinIOS.Unified/SQLite.Net.Tests.XamarinIOS.Unified.csproj index 86e685184..1daf8117f 100644 --- a/tests/SQLiteTouchTests/SQLiteTouchTests.csproj +++ b/tests/SQLite.Net.Tests.XamarinIOS.Unified/SQLite.Net.Tests.XamarinIOS.Unified.csproj @@ -3,89 +3,109 @@ Debug iPhoneSimulator - 10.0.0 - 2.0 - {D61A2E10-513B-4F20-8046-CAA914CEE437} - {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {0A947CD1-3C6F-415A-A122-233BAE3005FD} Exe - SQLiteTouchTests + SQLite.Net.Tests.XamarinIOS.Unified Resources - SQLiteTouchTests + SQLite.Net.Tests.XamarinIOS.Unified - True + true full - False + false bin\iPhoneSimulator\Debug DEBUG; prompt 4 - False - True - True + false + i386 None + Entitlements.plist + true + iPhone Developer + true - none - True + full + true bin\iPhoneSimulator\Release prompt 4 - False + false + i386 None + iPhone Developer + Entitlements.plist - True + true full - False + false bin\iPhone\Debug DEBUG; prompt 4 - False + false + ARMv7, ARM64 + true iPhone Developer - True - True + true + + - none - True + full + true bin\iPhone\Release prompt 4 - False + ARMv7, ARM64 + false iPhone Developer - ARMv7 - - none - True + full + true bin\iPhone\Ad-Hoc prompt 4 - False - True + false + ARMv7, ARM64 + true iPhone Distribution + Automatic:AdHoc + true - none - True + full + true bin\iPhone\AppStore prompt 4 - False + false + ARMv7, ARM64 + Automatic:AppStore iPhone Distribution - + + + + + + + + + packages.config + @@ -93,6 +113,9 @@ AsyncTests.cs + + BlobSerializationTest.cs + BooleanTest.cs @@ -102,27 +125,48 @@ CollateTest.cs + + ConnectionTrackingTest.cs + ContainsTest.cs + + CreateTableImplicitTest.cs + CreateTableTest.cs + + DateTimeOffsetTest.cs + DateTimeTest.cs + + DefaulAttributeTest.cs + DeleteTest.cs DropTableTest.cs + + EqualsTest.cs + ExceptionAssert.cs + + ExpressionTests.cs + GuidTests.cs + + IgnoreTest.cs + InheritanceTest.cs @@ -138,12 +182,24 @@ MappingTest.cs + + MigrationTest.cs + + + NotNullAttributeTest.cs + NullableTest.cs + + OpenTests.cs + ScalarTest.cs + + SerializableTest.cs + SkipTest.cs @@ -153,6 +209,9 @@ TestDb.cs + + TimeSpanTest.cs + TransactionTest.cs @@ -162,12 +221,20 @@ UniqueTest.cs - - SQLite.cs - - - SQLiteAsync.cs - - + + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + {3AB34E91-8E1A-442F-8E66-2494B371A890} + SQLite.Net.Async + + + {3173703F-8B1F-4772-9AE3-44913F413FB1} + SQLite.Net.Platform.XamarinIOS.Unified + + \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.XamarinIOS/AppDelegate.cs b/tests/SQLite.Net.Tests.XamarinIOS/AppDelegate.cs new file mode 100644 index 000000000..1cb9986b4 --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinIOS/AppDelegate.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.NUnit.UI; + +namespace SQLite.Net.Tests.XamarinIOS +{ + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to + // application events from iOS. + [Register("AppDelegate")] + public partial class AppDelegate : UIApplicationDelegate + { + // class-level declarations + UIWindow window; + TouchRunner runner; + + // + // This method is invoked when the application has loaded and is ready to run. In this + // method you should instantiate the window, load the UI into it and then make the window + // visible. + // + // You have 17 seconds to return from this method, or iOS will terminate your application. + // + public override bool FinishedLaunching(UIApplication app, NSDictionary options) + { + // create a new window instance based on the screen size + window = new UIWindow(UIScreen.MainScreen.Bounds); + runner = new TouchRunner(window); + + // register every tests included in the main application/assembly + runner.Add(System.Reflection.Assembly.GetExecutingAssembly()); + + window.RootViewController = new UINavigationController(runner.GetViewController()); + + // make the window visible + window.MakeKeyAndVisible(); + + return true; + } + } +} \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.XamarinIOS/Info.plist b/tests/SQLite.Net.Tests.XamarinIOS/Info.plist new file mode 100644 index 000000000..25455a180 --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinIOS/Info.plist @@ -0,0 +1,37 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + MinimumOSVersion + 6.0 + CFBundleDisplayName + SQLite.Net.Tests.XamarinIOS + CFBundleIdentifier + SQLite.Net.Tests.XamarinIOS + CFBundleVersion + + NSMainNibFile + + NSMainNibFile~ipad + + CFBundleIconFiles + + Default.png + Default@2x.png + Default-568h@2x.png + + + diff --git a/tests/SQLite.Net.Tests.XamarinIOS/Main.cs b/tests/SQLite.Net.Tests.XamarinIOS/Main.cs new file mode 100644 index 000000000..1040a79bd --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinIOS/Main.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using MonoTouch.Foundation; +using MonoTouch.UIKit; + +namespace SQLite.Net.Tests.XamarinIOS +{ + public class Application + { + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, "AppDelegate"); + } + } +} \ No newline at end of file diff --git a/tests/SQLite.Net.Tests.XamarinIOS/Properties/AssemblyInfo.cs b/tests/SQLite.Net.Tests.XamarinIOS/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..563d06668 --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinIOS/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SQLite.Net.Tests.XamarinIOS")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SQLite.Net.Tests.XamarinIOS")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2a5fa896-43b9-4ecb-89fa-bffd2ef24202")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tests/SQLite.Net.Tests.XamarinIOS/Resources/Default-568h@2x.png b/tests/SQLite.Net.Tests.XamarinIOS/Resources/Default-568h@2x.png new file mode 100644 index 000000000..b3f66780c Binary files /dev/null and b/tests/SQLite.Net.Tests.XamarinIOS/Resources/Default-568h@2x.png differ diff --git a/tests/SQLite.Net.Tests.XamarinIOS/Resources/Default.png b/tests/SQLite.Net.Tests.XamarinIOS/Resources/Default.png new file mode 100644 index 000000000..7ad63b043 Binary files /dev/null and b/tests/SQLite.Net.Tests.XamarinIOS/Resources/Default.png differ diff --git a/tests/SQLite.Net.Tests.XamarinIOS/Resources/Default@2x.png b/tests/SQLite.Net.Tests.XamarinIOS/Resources/Default@2x.png new file mode 100644 index 000000000..8d59426f3 Binary files /dev/null and b/tests/SQLite.Net.Tests.XamarinIOS/Resources/Default@2x.png differ diff --git a/tests/SQLite.Net.Tests.XamarinIOS/SQLite.Net.Tests.XamarinIOS.csproj b/tests/SQLite.Net.Tests.XamarinIOS/SQLite.Net.Tests.XamarinIOS.csproj new file mode 100644 index 000000000..b2c918c2c --- /dev/null +++ b/tests/SQLite.Net.Tests.XamarinIOS/SQLite.Net.Tests.XamarinIOS.csproj @@ -0,0 +1,112 @@ + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {4B386F57-D313-4842-AE9B-F54EDBF1EBD5} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + SQLite.Net.Tests.XamarinIOS + Resources + SQLiteNetTestsXamarinIOS + + + true + full + false + bin\iPhoneSimulator\Debug + DEBUG + prompt + 4 + false + None + true + + + none + true + bin\iPhoneSimulator\Release + prompt + 4 + false + None + + + true + full + false + bin\iPhone\Debug + DEBUG + prompt + 4 + false + true + iPhone Developer + + + none + true + bin\iPhone\Release + prompt + 4 + false + iPhone Developer + + + none + True + bin\iPhone\Ad-Hoc + prompt + 4 + False + iPhone Distribution + True + + + none + True + bin\iPhone\AppStore + prompt + 4 + False + iPhone Distribution + + + + + + + + + + + + + + + + + + + + + + + + + {3AB34E91-8E1A-442F-8E66-2494B371A890} + SQLite.Net.Async + + + {6377929d-6253-450d-bf4b-3e8ece2564f7} + SQLite.Net.Platform.XamarinIOS + + + {4971D437-0694-4297-A8CC-146CE08C3BD9} + SQLite.Net + + + + \ No newline at end of file diff --git a/tests/SQLite.Tests.csproj b/tests/SQLite.Tests.csproj deleted file mode 100644 index fbc9105e5..000000000 --- a/tests/SQLite.Tests.csproj +++ /dev/null @@ -1,73 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {6947A8F1-99BE-4DD1-AD4D-D89425CE67A2} - Library - SQLite.Tests - SQLite.Tests - - - True - full - False - bin\Debug - DEBUG - prompt - 4 - False - - - none - False - bin\Release - prompt - 4 - False - - - - - - False - - - - - - - - - - - - - - - - - - - - - - - - - - SQLiteAsync.cs - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/SQLiteMetroTests.sln b/tests/SQLiteMetroTests.sln deleted file mode 100644 index 56f8a3293..000000000 --- a/tests/SQLiteMetroTests.sln +++ /dev/null @@ -1,46 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 11 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLiteMetroTests", "SQLiteMetroTests\SQLiteMetroTests.csproj", "{909DE315-2F55-4A20-A9AD-460D4B2A3908}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|ARM = Release|ARM - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|ARM.ActiveCfg = Debug|ARM - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|ARM.Build.0 = Debug|ARM - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|ARM.Deploy.0 = Debug|ARM - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|Any CPU.Build.0 = Debug|Any CPU - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|x64.ActiveCfg = Debug|x64 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|x64.Build.0 = Debug|x64 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|x64.Deploy.0 = Debug|x64 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|x86.ActiveCfg = Debug|x86 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|x86.Build.0 = Debug|x86 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Debug|x86.Deploy.0 = Debug|x86 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|ARM.ActiveCfg = Release|ARM - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|ARM.Build.0 = Release|ARM - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|ARM.Deploy.0 = Release|ARM - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|Any CPU.ActiveCfg = Release|Any CPU - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|Any CPU.Build.0 = Release|Any CPU - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|Any CPU.Deploy.0 = Release|Any CPU - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|x64.ActiveCfg = Release|x64 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|x64.Build.0 = Release|x64 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|x64.Deploy.0 = Release|x64 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|x86.ActiveCfg = Release|x86 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|x86.Build.0 = Release|x86 - {909DE315-2F55-4A20-A9AD-460D4B2A3908}.Release|x86.Deploy.0 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/tests/SQLiteMetroTests/SQLiteMetroTests_TemporaryKey.pfx b/tests/SQLiteMetroTests/SQLiteMetroTests_TemporaryKey.pfx deleted file mode 100644 index 35d8f6238..000000000 Binary files a/tests/SQLiteMetroTests/SQLiteMetroTests_TemporaryKey.pfx and /dev/null differ diff --git a/tests/SQLiteTouchTests.sln b/tests/SQLiteTouchTests.sln deleted file mode 100644 index 220a4353a..000000000 --- a/tests/SQLiteTouchTests.sln +++ /dev/null @@ -1,32 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLiteTouchTests", "SQLiteTouchTests\SQLiteTouchTests.csproj", "{D61A2E10-513B-4F20-8046-CAA914CEE437}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|iPhoneSimulator = Debug|iPhoneSimulator - Release|iPhoneSimulator = Release|iPhoneSimulator - Debug|iPhone = Debug|iPhone - Release|iPhone = Release|iPhone - Ad-Hoc|iPhone = Ad-Hoc|iPhone - AppStore|iPhone = AppStore|iPhone - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D61A2E10-513B-4F20-8046-CAA914CEE437}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone - {D61A2E10-513B-4F20-8046-CAA914CEE437}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone - {D61A2E10-513B-4F20-8046-CAA914CEE437}.AppStore|iPhone.ActiveCfg = AppStore|iPhone - {D61A2E10-513B-4F20-8046-CAA914CEE437}.AppStore|iPhone.Build.0 = AppStore|iPhone - {D61A2E10-513B-4F20-8046-CAA914CEE437}.Debug|iPhone.ActiveCfg = Debug|iPhone - {D61A2E10-513B-4F20-8046-CAA914CEE437}.Debug|iPhone.Build.0 = Debug|iPhone - {D61A2E10-513B-4F20-8046-CAA914CEE437}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {D61A2E10-513B-4F20-8046-CAA914CEE437}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {D61A2E10-513B-4F20-8046-CAA914CEE437}.Release|iPhone.ActiveCfg = Release|iPhone - {D61A2E10-513B-4F20-8046-CAA914CEE437}.Release|iPhone.Build.0 = Release|iPhone - {D61A2E10-513B-4F20-8046-CAA914CEE437}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {D61A2E10-513B-4F20-8046-CAA914CEE437}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = SQLiteTouchTests\SQLiteTouchTests.csproj - EndGlobalSection -EndGlobal diff --git a/tests/ScalarTest.cs b/tests/ScalarTest.cs index 339d073cd..50fadd170 100644 --- a/tests/ScalarTest.cs +++ b/tests/ScalarTest.cs @@ -1,50 +1,46 @@ -using System; +using System.Collections.Generic; using System.Linq; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; -#endif +using SQLite.Net.Attributes; -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class ScalarTest - { - class TestTable - { - [PrimaryKey, AutoIncrement] - public int Id { get; set; } - public int Two { get; set; } - } - - const int Count = 100; - - SQLiteConnection CreateDb () - { - var db = new TestDb (); - db.CreateTable (); - var items = from i in Enumerable.Range (0, Count) - select new TestTable { Two = 2 }; - db.InsertAll (items); - Assert.AreEqual (Count, db.Table ().Count ()); - return db; - } - - - [Test] - public void Int32 () - { - var db = CreateDb (); - - var r = db.ExecuteScalar ("SELECT SUM(Two) FROM TestTable"); - - Assert.AreEqual (Count * 2, r); - } - } -} - + [TestFixture] + public class ScalarTest + { + private class TestTable + { + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + + public int Two { get; set; } + } + + private const int Count = 100; + + private SQLiteConnection CreateDb() + { + var db = new TestDb(); + db.CreateTable(); + IEnumerable items = from i in Enumerable.Range(0, Count) + select new TestTable + { + Two = 2 + }; + db.InsertAll(items); + Assert.AreEqual(Count, db.Table().Count()); + return db; + } + + + [Test] + public void Int32() + { + SQLiteConnection db = CreateDb(); + + var r = db.ExecuteScalar("SELECT SUM(Two) FROM TestTable"); + + Assert.AreEqual(Count*2, r); + } + } +} \ No newline at end of file diff --git a/tests/SerializableTest.cs b/tests/SerializableTest.cs new file mode 100644 index 000000000..0dc9801eb --- /dev/null +++ b/tests/SerializableTest.cs @@ -0,0 +1,278 @@ +using System; +using NUnit.Framework; +using SQLite.Net.Attributes; + +namespace SQLite.Net.Tests +{ + [TestFixture] + public class SerializableTests + { + private TestDb _db; + + [SetUp] + public void SetUp() + { + _db = new TestDb(); + _db.CreateTable(); + } + + [Test] + public void SupportsSerializableInt64() + { + Int64 value = Int64.MaxValue; + var model = new ComplexType { Int64Value = new SerializableInt64(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.Int64Value.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableInt32() + { + Int32 value = Int32.MaxValue; + var model = new ComplexType { Int32Value = new SerializableInt32(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.Int32Value.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableInt16() + { + Int16 value = Int16.MaxValue; + var model = new ComplexType { Int16Value = new SerializableInt16(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.Int16Value.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableString() + { + string value = "foo"; + var model = new ComplexType { StringValue = new SerializableString(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.StringValue.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableBoolean() + { + bool value = true; + var model = new ComplexType { BooleanValue = new SerializableBoolean(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.BooleanValue.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableByte() + { + byte value = 10; + var model = new ComplexType { ByteValue = new SerializableByte(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.ByteValue.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableSingle() + { + Single value = 0.0000001f; + var model = new ComplexType { SingleValue = new SerializableSingle(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.SingleValue.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableDouble() + { + Double value = 0.0000001; + var model = new ComplexType { DoubleValue = new SerializableDouble(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.DoubleValue.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableDecimal() + { + Decimal value = 0.0000001m; + var model = new ComplexType { DecimalValue = new SerializableDecimal(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.DecimalValue.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableTimeSpan() + { + TimeSpan value = TimeSpan.MaxValue; + var model = new ComplexType { TimeSpanValue = new SerializableTimeSpan(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.TimeSpanValue.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableDateTime() + { + DateTime value = DateTime.UtcNow; + var model = new ComplexType { DateTimeValue = new SerializableDateTime(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + var endOfPreviousSecond = value.AddMilliseconds(-value.Millisecond - 1); + var startOfNextSecond = value.AddMilliseconds(1000 - value.Millisecond + 1); + Assert.That(found.DateTimeValue.InnerValue, Is.InRange(endOfPreviousSecond, startOfNextSecond)); + } + + [Test] + public void SupportsSerializableByteArray() + { + byte[] value = new byte[] { 1, 2, 3, 4, 5 }; + var model = new ComplexType { ByteArrayValue = new SerializableByteArray(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.ByteArrayValue.InnerValue, Is.EqualTo(value)); + } + + [Test] + public void SupportsSerializableGuid() + { + Guid value = Guid.NewGuid(); + var model = new ComplexType { GuidValue = new SerializableGuid(value) }; + _db.Insert(model); + var found = _db.Get(m => m.ID == model.ID); + Assert.That(found.GuidValue.InnerValue, Is.EqualTo(value)); + } + + private class ComplexType + { + [AutoIncrement, PrimaryKey] + public int ID { get; set; } + + public SerializableInt64 Int64Value { get; set; } + public SerializableInt32 Int32Value { get; set; } + public SerializableInt16 Int16Value { get; set; } + public SerializableString StringValue { get; set; } + public SerializableBoolean BooleanValue { get; set; } + public SerializableByte ByteValue { get; set; } + public SerializableSingle SingleValue { get; set; } + public SerializableDouble DoubleValue { get; set; } + public SerializableDecimal DecimalValue { get; set; } + public SerializableTimeSpan TimeSpanValue { get; set; } + public SerializableDateTime DateTimeValue { get; set; } + public SerializableByteArray ByteArrayValue { get; set; } + public SerializableGuid GuidValue { get; set; } + } + + private class SerializableInt64 : Wrapper + { + public SerializableInt64(Int64 value) : base(value) + { + } + } + + private class SerializableInt32 : Wrapper + { + public SerializableInt32(Int32 value) : base(value) + { + } + } + + private class SerializableInt16 : Wrapper + { + public SerializableInt16(Int16 value) : base(value) + { + } + } + + private class SerializableString : Wrapper + { + public SerializableString(string value) : base(value) + { + } + } + + private class SerializableBoolean : Wrapper + { + public SerializableBoolean(Boolean value) : base(value) + { + } + } + + private class SerializableByte : Wrapper + { + public SerializableByte(Byte value) : base(value) + { + } + } + + private class SerializableSingle : Wrapper + { + public SerializableSingle(Single value) : base(value) + { + } + } + + private class SerializableDouble : Wrapper + { + public SerializableDouble(Double value) : base(value) + { + } + } + + private class SerializableDecimal : Wrapper + { + public SerializableDecimal(Decimal value) : base(value) + { + } + } + + private class SerializableTimeSpan : Wrapper + { + public SerializableTimeSpan(TimeSpan value) : base(value) + { + } + } + + private class SerializableDateTime : Wrapper + { + public SerializableDateTime(DateTime value) : base(value) + { + } + } + + private class SerializableByteArray : Wrapper + { + public SerializableByteArray(byte[] value) : base(value) + { + } + } + + private class SerializableGuid : Wrapper + { + public SerializableGuid(Guid value) : base(value) + { + } + } + + private abstract class Wrapper : ISerializable + { + public T InnerValue; + + public Wrapper(T value) + { + InnerValue = value; + } + + public T Serialize() + { + return InnerValue; + } + } + } +} + diff --git a/tests/SkipTest.cs b/tests/SkipTest.cs index e5b75fe40..e5141ba3e 100644 --- a/tests/SkipTest.cs +++ b/tests/SkipTest.cs @@ -1,23 +1,26 @@ using System; -using System.IO; using System.Collections.Generic; using System.Linq; -using System.Text; -using SQLite; +using NUnit.Framework; +using SQLite.Net.Attributes; -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; #else -using NUnit.Framework; +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -using System.Diagnostics; -namespace SQLite.Tests -{ +namespace SQLite.Net.Tests +{ [TestFixture] public class SkipTest { @@ -25,51 +28,53 @@ public class TestObj { [AutoIncrement, PrimaryKey] public int Id { get; set; } - public int Order { get; set; } - public override string ToString () + public int Order { get; set; } + + public override string ToString() { - return string.Format("[TestObj: Id={0}, Order={1}]", Id, Order); + return string.Format("[TestObj: Id={0}, Order={1}]", Id, Order); } - } + public class TestDb : SQLiteConnection { public TestDb(String path) - : base(path) + : base(new SQLitePlatformTest(), path) { - CreateTable(); + CreateTable(); } } - + [Test] public void Skip() { - var n = 100; - - var cq = from i in Enumerable.Range(1, n) - select new TestObj() { - Order = i - }; - var objs = cq.ToArray(); - var db = new TestDb(TestPath.GetTempFileName()); - - var numIn = db.InsertAll(objs); - Assert.AreEqual(numIn, n, "Num inserted must = num objects"); - - var q = from o in db.Table() - orderby o.Order - select o; - - var qs1 = q.Skip(1); - var s1 = qs1.ToList(); - Assert.AreEqual(n - 1, s1.Count); - Assert.AreEqual(2, s1[0].Order); - - var qs5 = q.Skip(5); - var s5 = qs5.ToList(); - Assert.AreEqual(n - 5, s5.Count); - Assert.AreEqual(6, s5[0].Order); + int n = 100; + + IEnumerable cq = from i in Enumerable.Range(1, n) + select new TestObj + { + Order = i + }; + TestObj[] objs = cq.ToArray(); + var db = new TestDb(TestPath.GetTempFileName()); + + int numIn = db.InsertAll(objs); + Assert.AreEqual(numIn, n, "Num inserted must = num objects"); + + TableQuery q = from o in db.Table() + orderby o.Order + select o; + + TableQuery qs1 = q.Skip(1); + List s1 = qs1.ToList(); + Assert.AreEqual(n - 1, s1.Count); + Assert.AreEqual(2, s1[0].Order); + + TableQuery qs5 = q.Skip(5); + List s5 = qs5.ToList(); + Assert.AreEqual(n - 5, s5.Count); + Assert.AreEqual(6, s5[0].Order); } } -} +} \ No newline at end of file diff --git a/tests/StringQueryTest.cs b/tests/StringQueryTest.cs index 721d6bb25..a0b2022ac 100644 --- a/tests/StringQueryTest.cs +++ b/tests/StringQueryTest.cs @@ -1,66 +1,67 @@ -using System; -using System.Linq; using System.Collections.Generic; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else +using System.Linq; using NUnit.Framework; -#endif -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class StringQueryTest - { - TestDb db; - - [SetUp] - public void SetUp () - { - db = new TestDb (); - db.CreateTable (); - - var prods = new[] { - new Product { Name = "Foo" }, - new Product { Name = "Bar" }, - new Product { Name = "Foobar" }, - }; - - db.InsertAll (prods); - } - - [Test] - public void StartsWith () - { - var fs = db.Table ().Where (x => x.Name.StartsWith ("F")).ToList (); - Assert.AreEqual (2, fs.Count); - - var bs = db.Table ().Where (x => x.Name.StartsWith ("B")).ToList (); - Assert.AreEqual (1, bs.Count); - } - - [Test] - public void EndsWith () - { - var fs = db.Table ().Where (x => x.Name.EndsWith ("ar")).ToList (); - Assert.AreEqual (2, fs.Count); - - var bs = db.Table ().Where (x => x.Name.EndsWith ("o")).ToList (); - Assert.AreEqual (1, bs.Count); - } - - [Test] - public void Contains () - { - var fs = db.Table ().Where (x => x.Name.Contains ("o")).ToList (); - Assert.AreEqual (2, fs.Count); - - var bs = db.Table ().Where (x => x.Name.Contains ("a")).ToList (); - Assert.AreEqual (2, bs.Count); - } - } -} + [TestFixture] + public class StringQueryTest + { + [SetUp] + public void SetUp() + { + db = new TestDb(); + db.CreateTable(); + + var prods = new[] + { + new Product + { + Name = "Foo" + }, + new Product + { + Name = "Bar" + }, + new Product + { + Name = "Foobar" + } + }; + + db.InsertAll(prods); + } + + private TestDb db; + + [Test] + public void Contains() + { + List fs = db.Table().Where(x => x.Name.Contains("o")).ToList(); + Assert.AreEqual(2, fs.Count); + + List bs = db.Table().Where(x => x.Name.Contains("a")).ToList(); + Assert.AreEqual(2, bs.Count); + } + + [Test] + public void EndsWith() + { + List fs = db.Table().Where(x => x.Name.EndsWith("ar")).ToList(); + Assert.AreEqual(2, fs.Count); + + List bs = db.Table().Where(x => x.Name.EndsWith("o")).ToList(); + Assert.AreEqual(1, bs.Count); + } + + [Test] + public void StartsWith() + { + List fs = db.Table().Where(x => x.Name.StartsWith("F")).ToList(); + Assert.AreEqual(2, fs.Count); + + List bs = db.Table().Where(x => x.Name.StartsWith("B")).ToList(); + Assert.AreEqual(1, bs.Count); + } + } +} \ No newline at end of file diff --git a/tests/TestDb.cs b/tests/TestDb.cs index 609c59f2e..7ce0d6380 100644 --- a/tests/TestDb.cs +++ b/tests/TestDb.cs @@ -1,75 +1,89 @@ using System; using System.IO; +using SQLite.Net.Attributes; -#if NETFX_CORE -class DescriptionAttribute : Attribute -{ - public DescriptionAttribute (string desc) - { - } -} +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -namespace SQLite.Tests + +namespace SQLite.Net.Tests { - public class Product - { - [AutoIncrement, PrimaryKey] - public int Id { get; set; } - public string Name { get; set; } - public decimal Price { get; set; } - - public uint TotalSales { get; set; } - } - public class Order - { - [AutoIncrement, PrimaryKey] - public int Id { get; set; } - public DateTime PlacedTime { get; set; } - } - public class OrderHistory { - [AutoIncrement, PrimaryKey] - public int Id { get; set; } - public int OrderId { get; set; } - public DateTime Time { get; set; } - public string Comment { get; set; } - } - public class OrderLine - { - [AutoIncrement, PrimaryKey] - public int Id { get; set; } + public class Product + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public string Name { get; set; } + public decimal Price { get; set; } + + public uint TotalSales { get; set; } + } + + public class Order + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public DateTime PlacedTime { get; set; } + } + + public class OrderHistory + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public int OrderId { get; set; } + public DateTime Time { get; set; } + public string Comment { get; set; } + } + + public class OrderLine + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + [Indexed("IX_OrderProduct", 1)] - public int OrderId { get; set; } + public int OrderId { get; set; } + [Indexed("IX_OrderProduct", 2)] public int ProductId { get; set; } - public int Quantity { get; set; } - public decimal UnitPrice { get; set; } - public OrderLineStatus Status { get; set; } - } - public enum OrderLineStatus { - Placed = 1, - Shipped = 100 - } - - public class TestDb : SQLiteConnection - { - public TestDb (bool storeDateTimeAsTicks = false) : base (TestPath.GetTempFileName (), storeDateTimeAsTicks) - { - Trace = true; - } - } - - public class TestPath - { - public static string GetTempFileName () - { -#if NETFX_CORE - var name = Guid.NewGuid () + ".sqlite"; - return Path.Combine (Windows.Storage.ApplicationData.Current.LocalFolder.Path, name); -#else - return Path.GetTempFileName (); -#endif - } - } -} + public int Quantity { get; set; } + public decimal UnitPrice { get; set; } + public OrderLineStatus Status { get; set; } + } + + public enum OrderLineStatus + { + Placed = 1, + Shipped = 100 + } + + public class TestDb : SQLiteConnection + { + public TestDb(bool storeDateTimeAsTicks = false) + : base(new SQLitePlatformTest(), TestPath.GetTempFileName(), storeDateTimeAsTicks) + { + TraceListener = DebugTraceListener.Instance; + } + } + + public class TestPath + { + public static string GetTempFileName() + { + return Path.GetTempFileName(); + } + } +} \ No newline at end of file diff --git a/tests/TimeSpanTest.cs b/tests/TimeSpanTest.cs new file mode 100644 index 000000000..7e6a94db9 --- /dev/null +++ b/tests/TimeSpanTest.cs @@ -0,0 +1,58 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using SQLite.Net.Async; +using SQLite.Net.Attributes; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; +#endif + + +namespace SQLite.Net.Tests +{ + [TestFixture] + public class TimeSpanTest + { + private class TestDb + { + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + + public TimeSpan Time { get; set; } + } + + + private async Task TestAsyncDateTime(SQLiteAsyncConnection db) + { + await db.CreateTableAsync(); + + var val1 = new TestDb + { + Time = new TimeSpan(1000), + }; + await db.InsertAsync(val1); + TestDb val2 = await db.GetAsync(val1.Id); + Assert.AreEqual(val1.Time, val2.Time); + } + + [Test] + public async Task TestTimeSpan() + { + var sqLiteConnectionPool = new SQLiteConnectionPool(new SQLitePlatformTest()); + var sqLiteConnectionString = new SQLiteConnectionString(TestPath.GetTempFileName(), true); + var db = new SQLiteAsyncConnection(() => sqLiteConnectionPool.GetConnection(sqLiteConnectionString)); + await TestAsyncDateTime(db); + } + } +} \ No newline at end of file diff --git a/tests/TransactionTest.cs b/tests/TransactionTest.cs index 77bd48cb0..dfb1a5dc6 100644 --- a/tests/TransactionTest.cs +++ b/tests/TransactionTest.cs @@ -1,126 +1,142 @@ using System; using System.Collections.Generic; using System.Linq; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TearDown = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestCleanupAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; +using SQLite.Net.Attributes; + +#if __WIN32__ +using SQLitePlatformTest = SQLite.Net.Platform.Win32.SQLitePlatformWin32; +#elif WINDOWS_PHONE +using SQLitePlatformTest = SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8; +#elif __WINRT__ +using SQLitePlatformTest = SQLite.Net.Platform.WinRT.SQLitePlatformWinRT; +#elif __IOS__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS; +#elif __ANDROID__ +using SQLitePlatformTest = SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid; +#else +using SQLitePlatformTest = SQLite.Net.Platform.Generic.SQLitePlatformGeneric; #endif -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class TransactionTest - { - private TestDb db; - private List testObjects; - - public class TestObj - { - [AutoIncrement, PrimaryKey] - public int Id { get; set; } - - public override string ToString() - { - return string.Format("[TestObj: Id={0}]", Id); - } - } - - public class TransactionTestException : Exception - { - } - - public class TestDb : SQLiteConnection - { - public TestDb(String path) : base(path) - { - CreateTable(); - } - } - - [SetUp] - public void Setup() - { - testObjects = Enumerable.Range(1, 20).Select(i => new TestObj()).ToList(); - - db = new TestDb(TestPath.GetTempFileName()); - db.InsertAll(testObjects); - } - - [TearDown] - public void TearDown() - { - if (db != null) { - db.Close(); - } - } - - [Test] - public void SuccessfulSavepointTransaction() - { - db.RunInTransaction(() => { - db.Delete(testObjects[0]); - db.Delete(testObjects[1]); - db.Insert(new TestObj()); - }); - - Assert.AreEqual(testObjects.Count - 1, db.Table().Count()); - } - - [Test] - public void FailSavepointTransaction() - { - try { - db.RunInTransaction(() => { - db.Delete(testObjects[0]); - - throw new TransactionTestException(); - }); - } catch (TransactionTestException) { - // ignore - } - - Assert.AreEqual(testObjects.Count, db.Table().Count()); - } - - [Test] - public void SuccessfulNestedSavepointTransaction() - { - db.RunInTransaction(() => { - db.Delete(testObjects[0]); - - db.RunInTransaction(() => { - db.Delete(testObjects[1]); - }); - }); - - Assert.AreEqual(testObjects.Count - 2, db.Table().Count()); - } - - [Test] - public void FailNestedSavepointTransaction() - { - try { - db.RunInTransaction(() => { - db.Delete(testObjects[0]); - - db.RunInTransaction(() => { - db.Delete(testObjects[1]); - - throw new TransactionTestException(); - }); - }); - } catch (TransactionTestException) { - // ignore - } - - Assert.AreEqual(testObjects.Count, db.Table().Count()); - } - } -} - + [TestFixture] + public class TransactionTest + { + [SetUp] + public void Setup() + { + testObjects = Enumerable.Range(1, 20).Select(i => new TestObj()).ToList(); + + db = new TestDb(TestPath.GetTempFileName()); + db.InsertAll(testObjects); + } + + [TearDown] + public void TearDown() + { + if (db != null) + { + db.Close(); + } + } + + private TestDb db; + private List testObjects; + + public class TestObj + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public override string ToString() + { + return string.Format("[TestObj: Id={0}]", Id); + } + } + + public class TransactionTestException : Exception + { + } + + public class TestDb : SQLiteConnection + { + public TestDb(String path) + : base(new SQLitePlatformTest(), path) + { + CreateTable(); + } + } + + [Test] + public void FailNestedSavepointTransaction() + { + try + { + db.RunInTransaction(() => + { + db.Delete(testObjects[0]); + + db.RunInTransaction(() => + { + db.Delete(testObjects[1]); + + throw new TransactionTestException(); + }); + }); + } + catch (TransactionTestException) + { + // ignore + } + + Assert.AreEqual(testObjects.Count, db.Table().Count()); + } + + [Test] + public void FailSavepointTransaction() + { + try + { + db.RunInTransaction(() => + { + db.Delete(testObjects[0]); + + throw new TransactionTestException(); + }); + } + catch (TransactionTestException) + { + // ignore + } + + Assert.AreEqual(testObjects.Count, db.Table().Count()); + } + + [Test] + public void SuccessfulNestedSavepointTransaction() + { + db.RunInTransaction(() => + { + db.Delete(testObjects[0]); + + db.RunInTransaction(() => { db.Delete(testObjects[1]); }); + }); + + Assert.AreEqual(testObjects.Count - 2, db.Table().Count()); + } + + [Test] + public void SuccessfulSavepointTransaction() + { + db.RunInTransaction(() => + { + db.Delete(testObjects[0]); + db.Delete(testObjects[1]); + db.Insert(new TestObj()); + }); + + Assert.AreEqual(testObjects.Count - 1, db.Table().Count()); + } + } +} \ No newline at end of file diff --git a/tests/UnicodeTest.cs b/tests/UnicodeTest.cs index 4bcd1d9e3..fc4306c2d 100644 --- a/tests/UnicodeTest.cs +++ b/tests/UnicodeTest.cs @@ -1,56 +1,49 @@ -using System; +using System.Collections.Generic; using System.Linq; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; -#endif - -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class UnicodeTest - { - [Test] - public void Insert () - { - var db = new TestDb (); - - db.CreateTable (); - - string testString = "\u2329\u221E\u232A"; - - db.Insert (new Product { - Name = testString, - }); - - var p = db.Get (1); - - Assert.AreEqual (testString, p.Name); - } - - [Test] - public void Query () - { - var db = new TestDb (); - - db.CreateTable (); - - string testString = "\u2329\u221E\u232A"; - - db.Insert (new Product { - Name = testString, - }); - - var ps = (from p in db.Table () where p.Name == testString select p).ToList (); - - Assert.AreEqual (1, ps.Count); - Assert.AreEqual (testString, ps [0].Name); - } - } -} + [TestFixture] + public class UnicodeTest + { + [Test] + public void Insert() + { + var db = new TestDb(); + + db.CreateTable(); + + string testString = "\u2329\u221E\u232A"; + + db.Insert(new Product + { + Name = testString, + }); + + var p = db.Get(1); + + Assert.AreEqual(testString, p.Name); + } + + [Test] + public void Query() + { + var db = new TestDb(); + + db.CreateTable(); + + string testString = "\u2329\u221E\u232A"; + + db.Insert(new Product + { + Name = testString, + }); + + List ps = (from p in db.Table() where p.Name == testString select p).ToList(); + + Assert.AreEqual(1, ps.Count); + Assert.AreEqual(testString, ps[0].Name); + } + } +} \ No newline at end of file diff --git a/tests/UniqueTest.cs b/tests/UniqueTest.cs index 6bf22684a..92a5d2387 100644 --- a/tests/UniqueTest.cs +++ b/tests/UniqueTest.cs @@ -1,81 +1,86 @@ using System; using System.Collections.Generic; using System.Linq; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else using NUnit.Framework; -#endif - +using SQLite.Net.Attributes; -namespace SQLite.Tests +namespace SQLite.Net.Tests { - [TestFixture] - public class UniqueIndexTest - { - public class TheOne { - [PrimaryKey, AutoIncrement] - public int ID { get; set; } + [TestFixture] + public class UniqueIndexTest + { + public class TheOne + { + [PrimaryKey, AutoIncrement] + public int ID { get; set; } + + [Unique(Name = "UX_Uno")] + public int Uno { get; set; } + + [Unique(Name = "UX_Dos")] + public int Dos { get; set; } - [Unique (Name = "UX_Uno")] - public int Uno { get; set;} + [Unique(Name = "UX_Dos")] + public int Tres { get; set; } - [Unique (Name = "UX_Dos")] - public int Dos { get; set;} - [Unique (Name = "UX_Dos")] - public int Tres { get; set;} + [Indexed(Name = "UX_Uno_bool", Unique = true)] + public int Cuatro { get; set; } - [Indexed (Name = "UX_Uno_bool", Unique = true)] - public int Cuatro { get; set;} + [Indexed(Name = "UX_Dos_bool", Unique = true)] + public int Cinco { get; set; } - [Indexed (Name = "UX_Dos_bool", Unique = true)] - public int Cinco { get; set;} - [Indexed (Name = "UX_Dos_bool", Unique = true)] - public int Seis { get; set;} - } + [Indexed(Name = "UX_Dos_bool", Unique = true)] + public int Seis { get; set; } + } - public class IndexColumns { - public int seqno { get; set;} - public int cid { get; set;} - public string name { get; set; } - } + public class IndexColumns + { + public int seqno { get; set; } + public int cid { get; set; } + public string name { get; set; } + } - public class IndexInfo { - public int seq { get; set;} - public string name { get; set;} - public bool unique { get; set;} - } + public class IndexInfo + { + public int seq { get; set; } + public string name { get; set; } + public bool unique { get; set; } + } - [Test] - public void CreateUniqueIndexes () - { - using (var db = new TestDb ()) { - db.CreateTable (); - var indexes = db.Query ("PRAGMA INDEX_LIST (\"TheOne\")"); - Assert.AreEqual (4, indexes.Count, "# of indexes"); - CheckIndex (db, indexes, "UX_Uno", true, "Uno"); - CheckIndex (db, indexes, "UX_Dos", true, "Dos", "Tres"); - CheckIndex (db, indexes, "UX_Uno_bool", true, "Cuatro"); - CheckIndex (db, indexes, "UX_Dos_bool", true, "Cinco", "Seis"); - } - } + private static void CheckIndex(TestDb db, List indexes, string iname, bool unique, + params string[] columns) + { + if (columns == null) + { + throw new Exception("Don't!"); + } + IndexInfo idx = indexes.SingleOrDefault(i => i.name == iname); + Assert.IsNotNull(idx, String.Format("Index {0} not found", iname)); + Assert.AreEqual(idx.unique, unique, + String.Format("Index {0} unique expected {1} but got {2}", iname, unique, idx.unique)); + List idx_columns = db.Query(String.Format("PRAGMA INDEX_INFO (\"{0}\")", iname)); + Assert.AreEqual(columns.Length, idx_columns.Count, + String.Format("# of columns: expected {0}, got {1}", columns.Length, idx_columns.Count)); + foreach (string col in columns) + { + Assert.IsNotNull(idx_columns.SingleOrDefault(c => c.name == col), + String.Format("Column {0} not in index {1}", col, idx.name)); + } + } - static void CheckIndex (TestDb db, List indexes, string iname, bool unique, params string [] columns) - { - if (columns == null) - throw new Exception ("Don't!"); - var idx = indexes.SingleOrDefault (i => i.name == iname); - Assert.IsNotNull (idx, String.Format ("Index {0} not found", iname)); - Assert.AreEqual (idx.unique, unique, String.Format ("Index {0} unique expected {1} but got {2}", iname, unique, idx.unique)); - var idx_columns = db.Query (String.Format ("PRAGMA INDEX_INFO (\"{0}\")", iname)); - Assert.AreEqual (columns.Length, idx_columns.Count, String.Format ("# of columns: expected {0}, got {1}", columns.Length, idx_columns.Count)); - foreach (var col in columns) { - Assert.IsNotNull (idx_columns.SingleOrDefault (c => c.name == col), String.Format ("Column {0} not in index {1}", col, idx.name)); - } - } - } -} + [Test] + public void CreateUniqueIndexes() + { + using (var db = new TestDb()) + { + db.CreateTable(); + List indexes = db.Query("PRAGMA INDEX_LIST (\"TheOne\")"); + Assert.AreEqual(4, indexes.Count, "# of indexes"); + CheckIndex(db, indexes, "UX_Uno", true, "Uno"); + CheckIndex(db, indexes, "UX_Dos", true, "Dos", "Tres"); + CheckIndex(db, indexes, "UX_Uno_bool", true, "Cuatro"); + CheckIndex(db, indexes, "UX_Dos_bool", true, "Cinco", "Seis"); + } + } + } +} \ No newline at end of file diff --git a/tests/packages.config b/tests/packages.config new file mode 100644 index 000000000..ad37a5282 --- /dev/null +++ b/tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file