Skip to content
This repository was archived by the owner on Nov 1, 2018. It is now read-only.

Add SqliteConnection.CreateCollation method #340

Merged
merged 8 commits into from
Apr 20, 2017
Merged

Add SqliteConnection.CreateCollation method #340

merged 8 commits into from
Apr 20, 2017

Conversation

AlexanderTaeschner
Copy link
Contributor

Addresses #19

@dnfclas
Copy link

dnfclas commented Mar 23, 2017

@AlexanderTaeschner,
Thanks for having already signed the Contribution License Agreement. Your agreement was validated by .NET Foundation. We will now review your pull request.
Thanks,
.NET Foundation Pull Request Bot

@bricelam
Copy link
Contributor

Per the contributing guidelines:

Before submitting a feature or substantial code contribution please discuss it with the team and ensure it follows the product roadmap.

Let's work together on a design before looking at any code. Could you add your proposal to the issue?

@bricelam bricelam closed this Mar 23, 2017
@bricelam
Copy link
Contributor

bricelam commented Apr 7, 2017

Re-opening. This is pretty close to the design we landed on. Would you mind updating it?

@bricelam bricelam reopened this Apr 7, 2017
@bricelam bricelam self-assigned this Apr 7, 2017
@AlexanderTaeschner
Copy link
Contributor Author

Updated to new API spec in #19.

/// <param name="name">Name of the collation.</param>
/// <param name="comparison">Method that compares two strings.</param>
public virtual void CreateCollation(string name, Comparison<string> comparison)
=> CreateSqlite3Collation(name, null, (_, s1, s2) => comparison(s1, s2));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I'd just call CreateCollation<object>(name, null,... and inline CreateSqlite3Collation into the other overload.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

/// <param name="comparison">Method that compares two strings, using additional state.</param>
public virtual void CreateCollation<T>(string name, T state, Func<T, string, string, int> comparison)
{
var rc = raw.sqlite3_create_collation(_db, name, state, (v, s1, s2) => comparison((T)v, s1, s2));
Copy link
Contributor

@bricelam bricelam Apr 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, we'll need to throw if the connection isn't open.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added check and test case.

/// </summary>
/// <param name="name">Name of the collation.</param>
/// <param name="comparison">Method that compares two strings.</param>
public virtual void CreateCollation(string name, Comparison<string> comparison)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing a null comparison will currently result in a NullReferenceException. We should either:

  1. Throw ArgumentNullException
  2. Support it by flowing null into sqlite3_create_collation (which removes the collation)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably validate name too if the native API gives its "misuse" error for null or empty values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opted for option 2 and added test.

() => connection.ExecuteScalar<long>("SELECT 'Νικοσ' = 'ΝΙΚΟΣ' COLLATE MY_NOCASE;"));

Assert.Equal(raw.SQLITE_ERROR, ex.SqliteErrorCode);
Assert.Contains("no such collation sequence", ex.Message);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't assert the message. (In case SQLite ever decides to localize.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think there's a PRAGMA you can use to see the registered collations. It might be better to use that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed assertion. Adding a complete ExecuteReader loop for analyzing the PRAGMA seems to be overly complex. Since sqlite version 3.16.0 there are table-valued functions for the PRAGMAs usable in SELECTs, but I don't think that we can rely on the use of such a new version.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OT: Are table-valued functions supported in general?

}

delegate_collation collation = comparison != null ? (v, s1, s2) => comparison((T)v, s1, s2) : (delegate_collation)null;
var rc = raw.sqlite3_create_collation(_db, name, state, collation);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to validate name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added validation.

@bricelam bricelam merged commit 36a3568 into aspnet:dev Apr 20, 2017
@AlexanderTaeschner AlexanderTaeschner deleted the Issue19 branch April 28, 2017 07:15
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants