banshee r5071 - in trunk/banshee: . src/Core/Banshee.Core/Banshee.Collection src/Core/Banshee.Services src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Collection.Database/Tests src/Core/Banshee.Services/Banshee.Database src/Core/Banshee.Services/Banshee.Query src/Core/Banshee.ThickClient src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor src/Libraries/Hyena src/Libraries/Hyena/Hyena src/Libraries/Hyena/Hyena.Data.Sqlite src/Libraries/Hyena/Hyena.Data.Sqlite/Tests src/Libraries/Hyena/Hyena/Tests
- From: gburt svn gnome org
- To: svn-commits-list gnome org
- Subject: banshee r5071 - in trunk/banshee: . src/Core/Banshee.Core/Banshee.Collection src/Core/Banshee.Services src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Collection.Database/Tests src/Core/Banshee.Services/Banshee.Database src/Core/Banshee.Services/Banshee.Query src/Core/Banshee.ThickClient src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor src/Libraries/Hyena src/Libraries/Hyena/Hyena src/Libraries/Hyena/Hyena.Data.Sqlite src/Libraries/Hyena/Hyena.Data.Sqlite/Tests src/Libraries/Hyena/Hyena/Tests
- Date: Thu, 26 Feb 2009 20:04:55 +0000 (UTC)
Author: gburt
Date: Thu Feb 26 20:04:55 2009
New Revision: 5071
URL: http://svn.gnome.org/viewvc/banshee?rev=5071&view=rev
Log:
2009-02-26 Gabriel Burt <gabriel burt gmail com>
Massive, awesomely-well-done patch by John Millikin adding proper support
for unicode-compatibile, case-insensitive, current-culture-aware
collation/sorting (BGO #499650)
* src/Core/Banshee.Core/Banshee.Collection/AlbumInfo.cs:
* src/Core/Banshee.Core/Banshee.Collection/ArtistInfo.cs:
* src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs: Save
String.Empty as null for *Sort properties.
* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumInfo.cs:
* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistInfo.cs:
* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs:
Add internal *SortKey properties that run their respective *Sort values
through Hyena.StringUtil.SortKey. Change *Lowered properties to internal.
* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs:
* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistListModel.cs:
* src/Core/Banshee.Services/Banshee.Query/BansheeQuery.cs:
Sort by the new *SortKey columns instead of the *Lowered columns, and use
the custom SQLite collation method (HYENA_COLLATION_KEY) for columns
without cached collation keys.
* src/Core/Banshee.Services/Makefile.am:
* src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseAlbumInfoTests.cs:
* src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseArtistInfoTests.cs:
* src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseTrackInfoTests.cs:
Test the *Lowered, *Sort, and *SortKey properties.
* src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs:
* src/Core/Banshee.Services/Banshee.Database/SortKeyUpdater.cs: If the
locale is different than the last run, regenerate the cached SortKey
values.
* src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs:
Add *SortKey columns for album/artist/title values. Since these columns
are very commonly sorted on, having the proper collation-key values
already generated gives us a performance win.
* src/Core/Banshee.Services/Banshee.Database/BansheeModelProvider.cs:
* src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs: Allow
turning of the table checking (that adds columns automatically).
* src/Core/Banshee.ThickClient/Makefile.am:
* src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml:
* src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SortingPage.cs:
Simple new tab in the track editor for modifying the *Sort properties.
* src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs: Handle
sqlifying byte[] as blobs.
* src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteUtils.cs: Recognize byte[]
as blobs, and add new HYENA_COLLATION_KEY custom SQLite function that uses
Hyena.StringUtils.SortKey.
* src/Libraries/Hyena/Hyena.Data.Sqlite/Tests/SqliteCommandTests.cs: Test
the sqlifying of various object types.
* src/Libraries/Hyena/Makefile.am:
* src/Libraries/Hyena/Hyena.Data.Sqlite/Tests/SqliteUtilTests.cs: Test the
collation and search custom methods.
* src/Libraries/Hyena/Hyena/StringUtil.cs: Add SortKey method that
generates a case-insensitive, current-culture-aware byte[] collation key.
* src/Libraries/Hyena/Hyena/Tests/StringUtilTests.cs: Test the new SortKey
method.
Added:
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/Tests/
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseAlbumInfoTests.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseArtistInfoTests.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseTrackInfoTests.cs
trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SortingPage.cs
trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/Tests/SqliteUtilTests.cs
Modified:
trunk/banshee/ChangeLog
trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/AlbumInfo.cs
trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/ArtistInfo.cs
trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumInfo.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistInfo.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistListModel.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeModelProvider.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Database/SortKeyUpdater.cs
trunk/banshee/src/Core/Banshee.Services/Banshee.Query/BansheeQuery.cs
trunk/banshee/src/Core/Banshee.Services/Makefile.am
trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml
trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs
trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs
trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteUtils.cs
trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/Tests/SqliteCommandTests.cs
trunk/banshee/src/Libraries/Hyena/Hyena/StringUtil.cs
trunk/banshee/src/Libraries/Hyena/Hyena/Tests/StringUtilTests.cs
trunk/banshee/src/Libraries/Hyena/Makefile.am
Modified: trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/AlbumInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/AlbumInfo.cs (original)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/AlbumInfo.cs Thu Feb 26 20:04:55 2009
@@ -60,7 +60,7 @@
public virtual string ArtistNameSort {
get { return artist_name_sort; }
- set { artist_name_sort = value; }
+ set { artist_name_sort = String.IsNullOrEmpty (value) ? null : value; }
}
public virtual string Title {
@@ -70,7 +70,7 @@
public virtual string TitleSort {
get { return title_sort; }
- set { title_sort = value; }
+ set { title_sort = String.IsNullOrEmpty (value) ? null : value; }
}
public virtual bool IsCompilation {
Modified: trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/ArtistInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/ArtistInfo.cs (original)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/ArtistInfo.cs Thu Feb 26 20:04:55 2009
@@ -26,6 +26,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
+
namespace Banshee.Collection
{
public class ArtistInfo : CacheableItem
@@ -56,7 +58,7 @@
public virtual string NameSort {
get { return name_sort; }
- set { name_sort = value; }
+ set { name_sort = String.IsNullOrEmpty (value) ? null : value; }
}
}
}
Modified: trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs (original)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs Thu Feb 26 20:04:55 2009
@@ -211,7 +211,7 @@
[Exportable (ExportName = "artistsort")]
public virtual string ArtistNameSort {
get { return artist_name_sort; }
- set { artist_name_sort = value; }
+ set { artist_name_sort = String.IsNullOrEmpty (value) ? null : value; }
}
[Exportable (ExportName = "album")]
@@ -223,7 +223,7 @@
[Exportable (ExportName = "albumsort")]
public virtual string AlbumTitleSort {
get { return album_title_sort; }
- set { album_title_sort = value; }
+ set { album_title_sort = String.IsNullOrEmpty (value) ? null : value; }
}
[Exportable]
@@ -235,7 +235,7 @@
[Exportable]
public virtual string AlbumArtistSort {
get { return album_artist_sort; }
- set { album_artist_sort = value; }
+ set { album_artist_sort = String.IsNullOrEmpty (value) ? null : value; }
}
[Exportable]
@@ -253,7 +253,7 @@
[Exportable (ExportName = "namesort")]
public virtual string TrackTitleSort {
get { return track_title_sort; }
- set { track_title_sort = value; }
+ set { track_title_sort = String.IsNullOrEmpty (value) ? null : value; }
}
[Exportable]
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumInfo.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumInfo.cs Thu Feb 26 20:04:55 2009
@@ -200,6 +200,16 @@
set { base.TitleSort = value; }
}
+ [DatabaseColumn(Select = false)]
+ internal byte[] TitleSortKey {
+ get { return Hyena.StringUtil.SortKey (TitleSort ?? Title); }
+ }
+
+ [DatabaseColumn(Select = false)]
+ internal string TitleLowered {
+ get { return Hyena.StringUtil.SearchKey (Title); }
+ }
+
[DatabaseColumn]
public override string ArtistName {
get { return base.ArtistName; }
@@ -213,12 +223,12 @@
}
[DatabaseColumn(Select = false)]
- protected string TitleLowered {
- get { return Hyena.StringUtil.SearchKey (Title); }
+ internal byte[] ArtistNameSortKey {
+ get { return Hyena.StringUtil.SortKey (ArtistNameSort ?? ArtistName); }
}
-
+
[DatabaseColumn(Select = false)]
- protected string ArtistNameLowered {
+ internal string ArtistNameLowered {
get { return Hyena.StringUtil.SearchKey (ArtistName); }
}
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs Thu Feb 26 20:04:55 2009
@@ -51,7 +51,7 @@
(SELECT CoreTracks.AlbumID FROM CoreTracks, CoreCache{0}
WHERE CoreCache.ModelID = {1} AND
CoreCache.ItemId = {2} {3})
- ORDER BY CoreAlbums.TitleLowered, CoreAlbums.ArtistNameLowered";
+ ORDER BY CoreAlbums.TitleSortKey, CoreAlbums.ArtistNameSortKey";
}
public override string FilterColumn {
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistInfo.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistInfo.cs Thu Feb 26 20:04:55 2009
@@ -134,7 +134,7 @@
}
[DatabaseColumn(Select = false)]
- protected string NameLowered {
+ internal string NameLowered {
get { return Hyena.StringUtil.SearchKey (Name); }
}
@@ -144,6 +144,11 @@
set { base.NameSort = value; }
}
+ [DatabaseColumn(Select = false)]
+ internal byte[] NameSortKey {
+ get { return Hyena.StringUtil.SortKey (NameSort ?? Name); }
+ }
+
[DatabaseColumn("MusicBrainzID")]
public override string MusicBrainzId {
get { return base.MusicBrainzId; }
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistListModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistListModel.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistListModel.cs Thu Feb 26 20:04:55 2009
@@ -50,7 +50,7 @@
(SELECT CoreTracks.ArtistID FROM CoreTracks, CoreCache{0}
WHERE CoreCache.ModelID = {1} AND
CoreCache.ItemID = {2} {3})
- ORDER BY NameLowered";
+ ORDER BY NameSortKey";
}
public override string FilterColumn {
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs Thu Feb 26 20:04:55 2009
@@ -450,14 +450,19 @@
set { base.TrackTitle = value; }
}
- [DatabaseColumn]
+ [DatabaseColumn ("TitleSort")]
public override string TrackTitleSort {
get { return base.TrackTitleSort; }
set { base.TrackTitleSort = value; }
}
+ [DatabaseColumn("TitleSortKey", Select = false)]
+ internal byte[] TrackTitleSortKey {
+ get { return Hyena.StringUtil.SortKey (TrackTitleSort ?? TrackTitle); }
+ }
+
[DatabaseColumn(Select = false)]
- protected string TitleLowered {
+ internal string TitleLowered {
get { return Hyena.StringUtil.SearchKey (TrackTitle); }
}
Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseAlbumInfoTests.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseAlbumInfoTests.cs Thu Feb 26 20:04:55 2009
@@ -0,0 +1,122 @@
+//
+// DatabaseAlbumInfoTests.cs
+//
+// Author:
+// John Millikin <jmillikin 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 ENABLE_TESTS
+
+using NUnit.Framework;
+using Banshee.Collection.Database;
+
+namespace Banshee.Collection.Database.Tests
+{
+ [TestFixture]
+ public class DatabaseAlbumInfoTests
+ {
+ static DatabaseAlbumInfoTests () {
+ Banshee.Database.BansheeDatabaseSettings.CheckTables = false;
+ }
+
+ protected void AssertTitleSort (string title, string title_sort, byte[] expected)
+ {
+ DatabaseAlbumInfo info = new DatabaseAlbumInfo ();
+ info.Title = title;
+ info.TitleSort = title_sort;
+ Assert.AreEqual (expected, info.TitleSortKey);
+ }
+
+ protected void AssertTitleLowered (string title, string expected)
+ {
+ DatabaseAlbumInfo info = new DatabaseAlbumInfo ();
+ info.Title = title;
+ Assert.AreEqual (expected, info.TitleLowered);
+ }
+
+ protected void AssertArtistNameSort (string name, string name_sort, byte[] expected)
+ {
+ DatabaseAlbumInfo info = new DatabaseAlbumInfo ();
+ info.ArtistName = name;
+ info.ArtistNameSort = name_sort;
+ Assert.AreEqual (expected, info.ArtistNameSortKey);
+ }
+
+ protected void AssertArtistNameLowered (string name, string expected)
+ {
+ DatabaseAlbumInfo info = new DatabaseAlbumInfo ();
+ info.ArtistName = name;
+ Assert.AreEqual (expected, info.ArtistNameLowered);
+ }
+
+ [Test]
+ public void TestWithoutTitleSortKey ()
+ {
+ AssertTitleSort ("", null, new byte[] {1, 1, 1, 1, 0});
+ AssertTitleSort ("a", null, new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertTitleSort ("a", "", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertTitleSort ("A", null, new byte[] {14, 2, 1, 1, 1, 1, 0});
+ }
+
+ [Test]
+ public void TestTitleSortKey ()
+ {
+ AssertTitleSort ("Title", "a", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertTitleSort ("Title", "A", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ }
+
+ [Test]
+ public void TestTitleLowered ()
+ {
+ AssertTitleLowered ("", "");
+ AssertTitleLowered ("A", "a");
+ AssertTitleLowered ("\u0104", "a");
+ }
+
+ [Test]
+ public void TestWithoutArtistNameSortKey ()
+ {
+ AssertArtistNameSort ("", null, new byte[] {1, 1, 1, 1, 0});
+ AssertArtistNameSort ("a", null, new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertArtistNameSort ("A", null, new byte[] {14, 2, 1, 1, 1, 1, 0});
+
+ AssertArtistNameSort ("a", "", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ }
+
+ [Test]
+ public void TestArtistNameSortKey ()
+ {
+ AssertArtistNameSort ("Title", "a", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertArtistNameSort ("Title", "A", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ }
+
+ [Test]
+ public void TestArtistNameLowered ()
+ {
+ AssertArtistNameLowered ("", "");
+ AssertArtistNameLowered ("A", "a");
+ AssertArtistNameLowered ("\u0104", "a");
+ }
+ }
+}
+
+#endif
Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseArtistInfoTests.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseArtistInfoTests.cs Thu Feb 26 20:04:55 2009
@@ -0,0 +1,84 @@
+//
+// DatabaseArtistInfoTests.cs
+//
+// Author:
+// John Millikin <jmillikin 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 ENABLE_TESTS
+
+using NUnit.Framework;
+using Banshee.Collection.Database;
+
+namespace Banshee.Collection.Database.Tests
+{
+ [TestFixture]
+ public class DatabaseArtistInfoTests
+ {
+ static DatabaseArtistInfoTests () {
+ Banshee.Database.BansheeDatabaseSettings.CheckTables = false;
+ }
+
+ protected void AssertNameSort (string name, string name_sort, byte[] expected)
+ {
+ DatabaseArtistInfo info = new DatabaseArtistInfo ();
+ info.Name = name;
+ info.NameSort = name_sort;
+ Assert.AreEqual (expected, info.NameSortKey);
+ }
+
+ protected void AssertNameLowered (string name, string expected)
+ {
+ DatabaseArtistInfo info = new DatabaseArtistInfo ();
+ info.Name = name;
+ Assert.AreEqual (expected, info.NameLowered);
+ }
+
+ [Test]
+ public void TestWithoutNameSortKey ()
+ {
+ AssertNameSort ("", null, new byte[] {1, 1, 1, 1, 0});
+ AssertNameSort ("a", null, new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertNameSort ("A", null, new byte[] {14, 2, 1, 1, 1, 1, 0});
+
+ AssertNameSort ("a", "", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ }
+
+ [Test]
+ public void TestNameSortKey ()
+ {
+ AssertNameSort ("Title", "a", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertNameSort ("Title", "A", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ }
+
+ [Test]
+ public void TestNameLowered ()
+ {
+ AssertNameLowered ("", "");
+ AssertNameLowered ("A", "a");
+ AssertNameLowered ("\u0104", "a");
+ }
+ }
+}
+
+#endif
+
Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseTrackInfoTests.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/Tests/DatabaseTrackInfoTests.cs Thu Feb 26 20:04:55 2009
@@ -0,0 +1,83 @@
+//
+// DatabaseTrackInfoTests.cs
+//
+// Author:
+// John Millikin <jmillikin 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 ENABLE_TESTS
+
+using NUnit.Framework;
+using Banshee.Collection.Database;
+
+namespace Banshee.Collection.Database.Tests
+{
+ [TestFixture]
+ public class DatabaseTrackInfoTests
+ {
+ static DatabaseTrackInfoTests () {
+ Banshee.Database.BansheeDatabaseSettings.CheckTables = false;
+ }
+
+ protected void AssertTitleSort (string title, string title_sort, byte[] expected)
+ {
+ DatabaseTrackInfo info = new DatabaseTrackInfo ();
+ info.TrackTitle = title;
+ info.TrackTitleSort = title_sort;
+ Assert.AreEqual (expected, info.TrackTitleSortKey);
+ }
+
+ protected void AssertTitleLowered (string title, string expected)
+ {
+ DatabaseTrackInfo info = new DatabaseTrackInfo ();
+ info.TrackTitle = title;
+ Assert.AreEqual (expected, info.TitleLowered);
+ }
+
+ [Test]
+ public void TestWithoutTitleSortKey ()
+ {
+ AssertTitleSort ("", null, new byte[] {1, 1, 1, 1, 0});
+ AssertTitleSort ("a", null, new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertTitleSort ("A", null, new byte[] {14, 2, 1, 1, 1, 1, 0});
+
+ AssertTitleSort ("a", "", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ }
+
+ [Test]
+ public void TestTitleSortKey ()
+ {
+ AssertTitleSort ("Title", "a", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertTitleSort ("Title", "A", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ }
+
+ [Test]
+ public void TestTitleLowered ()
+ {
+ AssertTitleLowered ("", "");
+ AssertTitleLowered ("A", "a");
+ AssertTitleLowered ("\u0104", "a");
+ }
+ }
+}
+
+#endif
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbConnection.cs Thu Feb 26 20:04:55 2009
@@ -71,6 +71,9 @@
lock (this) {
migrator.Migrate ();
migrator = null;
+
+ // Update cached sorting keys
+ SortKeyUpdater.Update ();
}
}
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs Thu Feb 26 20:04:55 2009
@@ -52,7 +52,7 @@
// NOTE: Whenever there is a change in ANY of the database schema,
// this version MUST be incremented and a migration method
// MUST be supplied to match the new version number
- protected const int CURRENT_VERSION = 24;
+ protected const int CURRENT_VERSION = 25;
protected const int CURRENT_METADATA_VERSION = 5;
#region Migration Driver
@@ -578,6 +578,20 @@
}
#endregion
+#region Version 25
+
+ [DatabaseVersion (25)]
+ private bool Migrate_25 ()
+ {
+ Execute ("ALTER TABLE CoreArtists ADD COLUMN NameSortKey BLOB");
+ Execute ("ALTER TABLE CoreAlbums ADD COLUMN ArtistNameSortKey BLOB");
+ Execute ("ALTER TABLE CoreAlbums ADD COLUMN TitleSortKey BLOB");
+ Execute ("ALTER TABLE CoreTracks ADD COLUMN TitleSortKey BLOB");
+ return true;
+ }
+
+#endregion
+
#pragma warning restore 0169
#region Fresh database setup
@@ -643,6 +657,7 @@
Title TEXT,
TitleLowered TEXT,
TitleSort TEXT,
+ TitleSortKey BLOB,
TrackNumber INTEGER,
TrackCount INTEGER,
Disc INTEGER,
@@ -687,6 +702,7 @@
Title TEXT,
TitleLowered TEXT,
TitleSort TEXT,
+ TitleSortKey BLOB,
ReleaseDate INTEGER,
Duration INTEGER,
@@ -696,6 +712,7 @@
ArtistName TEXT,
ArtistNameLowered TEXT,
ArtistNameSort TEXT,
+ ArtistNameSortKey BLOB,
Rating INTEGER
)
@@ -711,6 +728,7 @@
Name TEXT,
NameLowered TEXT,
NameSort TEXT,
+ NameSortKey BLOB,
Rating INTEGER
)
");
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeModelProvider.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeModelProvider.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeModelProvider.cs Thu Feb 26 20:04:55 2009
@@ -36,10 +36,16 @@
namespace Banshee.Database
{
+ // Used for disabling table-checks during testing
+ internal static class BansheeDatabaseSettings
+ {
+ internal static bool CheckTables = true;
+ }
+
public class BansheeModelProvider<T> : SqliteModelProvider<T> where T : new ()
{
public BansheeModelProvider (BansheeDbConnection connection, string table_name)
- : base (connection, table_name)
+ : base (connection, table_name, BansheeDatabaseSettings.CheckTables)
{
}
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Database/SortKeyUpdater.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Database/SortKeyUpdater.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Database/SortKeyUpdater.cs Thu Feb 26 20:04:55 2009
@@ -0,0 +1,69 @@
+//
+// SortKeyUpdater.cs
+//
+// Author:
+// John Millikin <jmillikin 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.Globalization;
+using Banshee.Configuration;
+using Banshee.ServiceStack;
+
+namespace Banshee.Database
+{
+ internal class SortKeyUpdater
+ {
+ public static void Update ()
+ {
+ string locale = CultureInfo.CurrentCulture.Name;
+ Hyena.Log.DebugFormat ("locale = {0}, previous = {1}", locale, PreviousLocale);
+ if (locale != PreviousLocale) {
+ ForceUpdate (locale);
+ }
+ }
+
+ public static void ForceUpdate ()
+ {
+ ForceUpdate (CultureInfo.CurrentCulture.Name);
+ }
+
+ protected static void ForceUpdate (string new_locale)
+ {
+ BansheeDbConnection db = ServiceManager.DbConnection;
+ db.Execute ("BEGIN");
+ db.Execute (@"UPDATE CoreArtists SET NameSortKey = HYENA_COLLATION_KEY(IFNULL(NameSort,Name))");
+ db.Execute (@"UPDATE CoreAlbums SET TitleSortKey = HYENA_COLLATION_KEY(IFNULL(TitleSort,Title)),
+ ArtistNameSortKey = HYENA_COLLATION_KEY(IFNULL(ArtistNameSort, ArtistName))");
+ db.Execute (@"UPDATE CoreTracks SET TitleSortKey = HYENA_COLLATION_KEY(IFNULL(TitleSort,Title))");
+
+ DatabaseConfigurationClient.Client.Set<string> ("SortKeyLocale", new_locale);
+ db.Execute ("COMMIT");
+ }
+
+ protected static string PreviousLocale {
+ get {
+ return DatabaseConfigurationClient.Client.Get<string> ("SortKeyLocale", "");
+ }
+ }
+ }
+}
Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Query/BansheeQuery.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Query/BansheeQuery.cs (original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Query/BansheeQuery.cs Thu Feb 26 20:04:55 2009
@@ -337,7 +337,7 @@
PlayCountField.ShortLabel = Catalog.GetString ("Plays");
}
- private const string default_sort = @"CoreAlbums.ArtistNameLowered ASC, CoreAlbums.TitleLowered ASC, CoreTracks.Disc ASC, CoreTracks.TrackNumber ASC";
+ private const string default_sort = @"CoreAlbums.ArtistNameSortKey ASC, CoreAlbums.TitleSortKey ASC, CoreTracks.Disc ASC, CoreTracks.TrackNumber ASC";
public static string GetSort (string key)
{
return GetSort (key, false);
@@ -353,40 +353,40 @@
case "track":
case "grouping":
sort_query = String.Format (@"
- CoreAlbums.ArtistNameLowered ASC,
- CoreAlbums.TitleLowered ASC,
+ CoreAlbums.ArtistNameSortKey ASC,
+ CoreAlbums.TitleSortKey ASC,
CoreTracks.Disc ASC,
CoreTracks.TrackNumber {0}", ascDesc);
break;
case "albumartist":
sort_query = String.Format (@"
- CoreAlbums.ArtistNameLowered {0},
- CoreAlbums.TitleLowered ASC,
+ CoreAlbums.ArtistNameSortKey {0},
+ CoreAlbums.TitleSortKey ASC,
CoreTracks.Disc ASC,
CoreTracks.TrackNumber ASC", ascDesc);
break;
case "artist":
sort_query = String.Format (@"
- CoreArtists.NameLowered {0},
- CoreAlbums.TitleLowered ASC,
+ CoreArtists.NameSortKey {0},
+ CoreAlbums.TitleSortKey ASC,
CoreTracks.Disc ASC,
CoreTracks.TrackNumber ASC", ascDesc);
break;
case "album":
sort_query = String.Format (@"
- CoreAlbums.TitleLowered {0},
+ CoreAlbums.TitleSortKey {0},
CoreTracks.Disc ASC,
CoreTracks.TrackNumber ASC", ascDesc);
break;
case "title":
sort_query = String.Format (@"
- CoreTracks.TitleLowered {0},
- CoreAlbums.ArtistNameLowered ASC,
- CoreAlbums.TitleLowered ASC", ascDesc);
+ CoreTracks.TitleSortKey {0},
+ CoreAlbums.ArtistNameSortKey ASC,
+ CoreAlbums.TitleSortKey ASC", ascDesc);
break;
case "random":
@@ -395,8 +395,8 @@
case "disc":
sort_query = String.Format (@"
- CoreAlbums.ArtistNameLowered ASC,
- CoreAlbums.TitleLowered ASC,
+ CoreAlbums.ArtistNameSortKey ASC,
+ CoreAlbums.TitleSortKey ASC,
CoreTracks.Disc {0},
CoreTracks.TrackNumber ASC", ascDesc);
break;
@@ -406,18 +406,26 @@
case "lastplayed":
case "lastskipped":
column = String.Format ("{0}stamp", key);
- goto case "comment";
+ goto case "year";
case "added":
column = "dateaddedstamp";
- goto case "comment";
+ goto case "year";
+
+ case "conductor":
+ case "genre":
+ case "composer":
+ case "comment":
+ sort_query = String.Format (
+ "HYENA_COLLATION_KEY(CoreTracks.{0}) {1}, {2}",
+ column ?? key, ascDesc, default_sort
+ );
+ break;
case "year":
case "bitrate":
case "bpm":
- case "conductor":
case "trackcount":
case "disccount":
- case "genre":
case "duration":
case "rating":
case "playcount":
@@ -428,9 +436,7 @@
case "dateaddedstamp":
case "uri":
case "mimetype":
- case "composer":
case "licenseuri":
- case "comment":
sort_query = String.Format (
"CoreTracks.{0} {1}, {2}",
column ?? key, ascDesc, default_sort
Modified: trunk/banshee/src/Core/Banshee.Services/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Makefile.am (original)
+++ trunk/banshee/src/Core/Banshee.Services/Makefile.am Thu Feb 26 20:04:55 2009
@@ -22,6 +22,9 @@
Banshee.Collection.Database/IDatabaseTrackModelCache.cs \
Banshee.Collection.Database/IDatabaseTrackModelProvider.cs \
Banshee.Collection.Database/QueryFilterInfo.cs \
+ Banshee.Collection.Database/Tests/DatabaseAlbumInfoTests.cs \
+ Banshee.Collection.Database/Tests/DatabaseArtistInfoTests.cs \
+ Banshee.Collection.Database/Tests/DatabaseTrackInfoTests.cs \
Banshee.Collection.Indexer/CollectionIndexer.cs \
Banshee.Collection.Indexer/CollectionIndexerService.cs \
Banshee.Collection.Indexer/ICollectionIndexer.cs \
@@ -48,6 +51,7 @@
Banshee.Database/BansheeDbFormatMigrator.cs \
Banshee.Database/BansheeModelCache.cs \
Banshee.Database/BansheeModelProvider.cs \
+ Banshee.Database/SortKeyUpdater.cs \
Banshee.Equalizer/EqualizerManager.cs \
Banshee.Equalizer/EqualizerSetting.cs \
Banshee.Equalizer/EqualizerSettingEvent.cs \
Added: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SortingPage.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SortingPage.cs Thu Feb 26 20:04:55 2009
@@ -0,0 +1,76 @@
+//
+// SortingPage.cs
+//
+// Author:
+// John Millikin <jmillikin 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 Mono.Unix;
+using Gtk;
+
+using Banshee.Collection;
+
+namespace Banshee.Gui.TrackEditor
+{
+ public class SortingPage : FieldPage, ITrackEditorPage
+ {
+ public int Order {
+ get { return 30; }
+ }
+
+ public string Title {
+ get { return Catalog.GetString ("Sorting"); }
+ }
+
+ protected override void AddFields ()
+ {
+ AddField (this, new TextEntry (),
+ Catalog.GetString ("Set all sort track titles to this value"),
+ delegate { return Catalog.GetString ("Sort Track Title:"); },
+ delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.TrackTitleSort; },
+ delegate (EditorTrackInfo track, Widget widget) { track.TrackTitleSort = ((TextEntry)widget).Text; }
+ );
+
+ AddField (this, new TextEntry (),
+ Catalog.GetString ("Set all sort track artists to this value"),
+ delegate { return Catalog.GetString ("Sort Track Artist:"); },
+ delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.ArtistNameSort; },
+ delegate (EditorTrackInfo track, Widget widget) { track.ArtistNameSort = ((TextEntry)widget).Text; }
+ );
+
+ AddField (this, new TextEntry (),
+ Catalog.GetString ("Set all sort album artists to this value"),
+ delegate { return Catalog.GetString ("Sort Album Artist:"); },
+ delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.AlbumArtistSort; },
+ delegate (EditorTrackInfo track, Widget widget) { track.AlbumArtistSort = ((TextEntry)widget).Text; }
+ );
+
+ AddField (this, new TextEntry (),
+ Catalog.GetString ("Set all sort album titles to this value"),
+ delegate { return Catalog.GetString ("Sort Album Title:"); },
+ delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.AlbumTitleSort; },
+ delegate (EditorTrackInfo track, Widget widget) { track.AlbumTitleSort = ((TextEntry)widget).Text; }
+ );
+ }
+ }
+}
Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml (original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml Thu Feb 26 20:04:55 2009
@@ -23,6 +23,7 @@
<Extension path="/Banshee/Gui/TrackEditor/NotebookPage">
<TrackEditorPage class="Banshee.Gui.TrackEditor.BasicTrackDetailsPage"/>
<TrackEditorPage class="Banshee.Gui.TrackEditor.ExtraTrackDetailsPage"/>
+ <TrackEditorPage class="Banshee.Gui.TrackEditor.SortingPage"/>
<!--<TrackEditorPage class="Banshee.Gui.TrackEditor.LyricsPage"/>-->
<TrackEditorPage class="Banshee.Gui.TrackEditor.StatisticsPage"/>
<!--<TrackEditorPage class="Banshee.Gui.TrackEditor.HelpPage"/>-->
Modified: trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am (original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am Thu Feb 26 20:04:55 2009
@@ -72,6 +72,7 @@
Banshee.Gui.TrackEditor/PageType.cs \
Banshee.Gui.TrackEditor/RangeEntry.cs \
Banshee.Gui.TrackEditor/RatingEntry.cs \
+ Banshee.Gui.TrackEditor/SortingPage.cs \
Banshee.Gui.TrackEditor/SpinButtonEntry.cs \
Banshee.Gui.TrackEditor/StatisticsPage.cs \
Banshee.Gui.TrackEditor/SyncButton.cs \
Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs Thu Feb 26 20:04:55 2009
@@ -207,7 +207,7 @@
return this;
}
- private static object SqlifyObject (object o)
+ public static object SqlifyObject (object o)
{
if (o is string) {
return String.Format ("'{0}'", (o as string).Replace ("'", "''"));
@@ -217,6 +217,9 @@
return ((bool)o) ? "1" : "0";
} else if (o == null) {
return "NULL";
+ } else if (o is byte[]) {
+ string hex = BitConverter.ToString (o as byte[]).Replace ("-", "");
+ return String.Format ("X'{0}'", hex);
} else if (o is Array) {
StringBuilder sb = new StringBuilder ();
bool first = true;
Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs Thu Feb 26 20:04:55 2009
@@ -43,6 +43,7 @@
private DatabaseColumn key;
private int key_select_column_index;
private HyenaSqliteConnection connection;
+ private bool check_table = true;
private HyenaSqliteCommand create_command;
private HyenaSqliteCommand insert_command;
@@ -86,15 +87,20 @@
public HyenaSqliteConnection Connection {
get { return connection; }
}
-
+
protected SqliteModelProvider (HyenaSqliteConnection connection)
{
this.connection = connection;
}
+
+ public SqliteModelProvider (HyenaSqliteConnection connection, string table_name) : this (connection, table_name, true)
+ {
+ }
- public SqliteModelProvider (HyenaSqliteConnection connection, string table_name) : this (connection)
+ public SqliteModelProvider (HyenaSqliteConnection connection, string table_name, bool checkTable) : this (connection)
{
this.table_name = table_name;
+ this.check_table = checkTable;
Init ();
}
@@ -126,8 +132,10 @@
key_select_column_index = select_columns.IndexOf (key);
- CheckVersion ();
- CheckTable ();
+ if (check_table) {
+ CheckVersion ();
+ CheckTable ();
+ }
}
protected virtual void CheckVersion ()
Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteUtils.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteUtils.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteUtils.cs Thu Feb 26 20:04:55 2009
@@ -42,6 +42,8 @@
} else if (type == typeof (int) || type == typeof (long) || type == typeof (bool)
|| type == typeof (DateTime) || type == typeof (TimeSpan) || type.IsEnum) {
return "INTEGER";
+ } else if (type == typeof (byte[])) {
+ return "BLOB";
} else {
throw new Exception (String.Format (
"The type {0} cannot be bound to a database column.", type.Name));
@@ -123,11 +125,21 @@
return builder.ToString ();
}
}
+
+ [SqliteFunction (Name = "HYENA_COLLATION_KEY", FuncType = FunctionType.Scalar, Arguments = 1)]
+ internal class CollationKeyFunction : SqliteFunction
+ {
+ public override object Invoke (object[] args)
+ {
+ return Hyena.StringUtil.SortKey (args[0] as string);
+ }
+ }
[SqliteFunction (Name = "HYENA_SEARCH_KEY", FuncType = FunctionType.Scalar, Arguments = 1)]
internal class SearchKeyFunction : SqliteFunction
{
- public override object Invoke (object[] args) {
+ public override object Invoke (object[] args)
+ {
return Hyena.StringUtil.SearchKey (args[0] as string);
}
}
Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/Tests/SqliteCommandTests.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/Tests/SqliteCommandTests.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/Tests/SqliteCommandTests.cs Thu Feb 26 20:04:55 2009
@@ -106,6 +106,62 @@
return tf.GetValue (cmd, null) as string;
}
}
+
+ [TestFixture]
+ public class ObjectToSqlTests
+ {
+ protected void AssertToSql (object o, object expected)
+ {
+ Assert.AreEqual (expected, HyenaSqliteCommand.SqlifyObject (o));
+ }
+
+ [Test]
+ public void TestNull ()
+ {
+ AssertToSql (null, "NULL");
+ }
+
+ [Test]
+ public void TestBool ()
+ {
+ AssertToSql (false, "0");
+ AssertToSql (true, "1");
+ }
+
+ [Test]
+ public void TestString ()
+ {
+ AssertToSql ("", "''");
+ AssertToSql ("test", "'test'");
+ AssertToSql ("te'st", "'te''st'");
+ }
+
+ [Test]
+ public void TestByteArray ()
+ {
+ // BLOB notation
+ AssertToSql (new byte[] {}, "X''");
+ AssertToSql (new byte[] {0x10, 0x20, 0x30}, "X'102030'");
+ }
+
+ [Test]
+ public void TestOtherArray ()
+ {
+ AssertToSql (new object[] {}, "");
+ AssertToSql (new object[] {"a"}, "'a'");
+ AssertToSql (new object[] {"a", "b"}, "'a','b'");
+ }
+
+ [Test]
+ public void TestDateTime ()
+ {
+ // Returned using local time, not UTC
+ AssertToSql (new DateTime (2000, 1, 2), 946792800);
+
+ // Disregards milliseconds
+ AssertToSql (new DateTime (2000, 1, 2, 10, 9, 8, 7), 946829348);
+ }
+ }
}
#endif
Added: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/Tests/SqliteUtilTests.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/Tests/SqliteUtilTests.cs Thu Feb 26 20:04:55 2009
@@ -0,0 +1,86 @@
+//
+// SqliteUtilTests.cs
+//
+// Author:
+// John Millikin <jmillikin 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 ENABLE_TESTS
+
+using NUnit.Framework;
+using Hyena.Data.Sqlite;
+
+namespace Hyena.Data.Sqlite.Tests
+{
+ [TestFixture]
+ public class CollationKeyTests
+ {
+ protected void CollationKeyTest (object before, object after)
+ {
+ Assert.AreEqual (after, (new CollationKeyFunction ()).Invoke (new object[] {before}));
+ }
+
+ [Test]
+ public void TestNull ()
+ {
+ CollationKeyTest (null, null);
+ CollationKeyTest (System.DBNull.Value, null);
+ }
+
+ [Test]
+ public void TestKey ()
+ {
+ // See Hyena.StringUtil.Tests for full tests. This just checks that
+ // the collation function is actually being used.
+ CollationKeyTest ("", new byte[] {1, 1, 1, 1, 0});
+ CollationKeyTest ("\u0104", new byte[] {14, 2, 1, 27, 1, 1, 1, 0});
+ }
+ }
+
+ [TestFixture]
+ public class SearchKeyTests
+ {
+ protected void SearchKeyTest (object before, object after)
+ {
+ Assert.AreEqual (after, (new SearchKeyFunction ()).Invoke (new object[] {before}));
+ }
+
+ [Test]
+ public void TestNull ()
+ {
+ SearchKeyTest (null, null);
+ SearchKeyTest (System.DBNull.Value, null);
+ }
+
+ [Test]
+ public void TestKey ()
+ {
+ // See Hyena.StringUtil.Tests for full tests. This just checks that
+ // the search key function is actually being used.
+ SearchKeyTest ("", "");
+ SearchKeyTest ("\u0104", "a");
+ }
+ }
+}
+
+#endif
+
Modified: trunk/banshee/src/Libraries/Hyena/Hyena/StringUtil.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena/StringUtil.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena/StringUtil.cs Thu Feb 26 20:04:55 2009
@@ -232,6 +232,13 @@
return new Regex (regex_str, RegexOptions.Compiled);
}
+ private static CompareInfo culture_compare_info = CultureInfo.CurrentCulture.CompareInfo;
+ public static byte[] SortKey (string orig)
+ {
+ if (orig == null) { return null; }
+ return culture_compare_info.GetSortKey (orig, CompareOptions.IgnoreCase).KeyData;
+ }
+
public static string EscapeFilename (string input)
{
if (input == null)
Modified: trunk/banshee/src/Libraries/Hyena/Hyena/Tests/StringUtilTests.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena/Tests/StringUtilTests.cs (original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena/Tests/StringUtilTests.cs Thu Feb 26 20:04:55 2009
@@ -279,6 +279,35 @@
AssertProduces ("Greetings! -* äå?", "Greetings! -_ äå_");
}
}
+
+ [TestFixture]
+ public class SortKeyTests
+ {
+ private void AssertSortKey (string before, object after)
+ {
+ Assert.AreEqual (after, StringUtil.SortKey (before));
+ }
+
+ [Test]
+ public void TestNull ()
+ {
+ AssertSortKey (null, null);
+ }
+
+ [Test]
+ public void TestEmpty ()
+ {
+ AssertSortKey ("", new byte[] {1, 1, 1, 1, 0});
+ }
+
+ [Test]
+ public void TestSortKey ()
+ {
+ AssertSortKey ("a", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertSortKey ("A", new byte[] {14, 2, 1, 1, 1, 1, 0});
+ AssertSortKey ("\u0104", new byte[] {14, 2, 1, 27, 1, 1, 1, 0,});
+ }
+ }
}
#endif
Modified: trunk/banshee/src/Libraries/Hyena/Makefile.am
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Makefile.am (original)
+++ trunk/banshee/src/Libraries/Hyena/Makefile.am Thu Feb 26 20:04:55 2009
@@ -31,6 +31,7 @@
Hyena.Data.Sqlite/Tests/DbBoundType.cs \
Hyena.Data.Sqlite/Tests/SqliteCommandTests.cs \
Hyena.Data.Sqlite/Tests/SqliteModelProviderTests.cs \
+ Hyena.Data.Sqlite/Tests/SqliteUtilTests.cs \
Hyena.Data/ArrayModelCache.cs \
Hyena.Data/ColumnDescription.cs \
Hyena.Data/DictionaryModelCache.cs \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]