Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binary order for PostgreSql and Sqlite what Provider or Strategy to use. #12

Open
borisdj opened this issue Jul 23, 2019 · 6 comments · May be fixed by #23
Open

Binary order for PostgreSql and Sqlite what Provider or Strategy to use. #12

borisdj opened this issue Jul 23, 2019 · 6 comments · May be fixed by #23

Comments

@borisdj
Copy link

borisdj commented Jul 23, 2019

For SqlServer Sequential Guid creation I have:

public static class SeqGuid
{
    private static ICombProvider SqlNoRepeatCombs = new SqlCombProvider(new UnixDateTimeStrategy(), new UtcNoRepeatTimestampProvider().GetTimestamp);

    public static Guid Create()
    {
        return SqlNoRepeatCombs.Create();
    }
}

How to configure the same for binary order ?

@richardtallent
Copy link
Owner

Hi Boris,

This is untested, but something like this should work. I've set the IncrementMs lower since the UnixDateTimeStrategy has 1ms resolution and thus we don't need to bump the timestamp as much when there is a collision as we have to with the embedded MSSQL datetime value.

public static class SeqGuid {
  private static readonly ICombProvider provider;
  static SeqGuid() {
    var s = new UnixDateTimeStrategy();
    var t = new UtcNoRepeatTimestampProvider() { IncrementMs = 2 };
    provider = new PostgreSqlCombProvider(s, t.GetTimestamp);
  }
  public static Guid Create() => provider.Create();
}

@borisdj
Copy link
Author

borisdj commented Jul 25, 2019

Thx
Additionaly
PostgreSqlCombProvider is for PostgreSql which uses SequentialAsString.
Sqlite when storing Guid in BLOB uses SequentialAsBinary, which is different.
I have tested it with Guid from this class SequentialGuid
Only have replaces lines 91:

var totalBytes = guidBytes.Concat(sequenceBytes).ToArray();

with

byte[] totalBytes = null;
switch (GuidType)
{
    case SequentialGuidType.SequentialAsString:
        totalBytes = sequenceBytes.Concat(guidBytes).ToArray();
        Array.Reverse(totalBytes, 0, 4);
        Array.Reverse(totalBytes, 4, 2);
        break;
    case SequentialGuidType.SequentialAtEnd:
        totalBytes = guidBytes.Concat(sequenceBytes).ToArray();
        break;
    case SequentialGuidType.SequentialAsBinary:
        totalBytes = sequenceBytes.Concat(guidBytes).ToArray();
        break;
}

Where SequentialGuidType is enum:

public enum SequentialGuidType
{
    /// <summary>
    /// The GUID should be sequential when formatted using the
    /// <see cref="Guid.ToString()" /> method. Best for PostgreSQL.
    /// </summary>
    SequentialAsString,

    /// <summary>
    /// The GUID should be sequential when formatted using the
    /// <see cref="Guid.ToByteArray" /> method.
    /// </summary>
    SequentialAsBinary,

    /// <summary>
    /// The sequential portion of the GUID should be located at the end
    /// of the Data4 block. Best for MsSQL.
    /// </summary>
    SequentialAtEnd
}

This way I get correct order in Sqlite.

Does your lib. have an BinaryCombProvider or SqliteCombProvider or how to get similar result?

Orders:

Database GUID Column SequentialGuidType Value
Microsoft SQL Server uniqueidentifier SequentialAtEnd
MySQL char(36) SequentialAsString
Oracle raw(16) SequentialAsBinary
PostgreSQL uuid SequentialAsString
SQLite varies varies

@richardtallent
Copy link
Owner

Good to know! I don't have a SQLiteCombProvider, but adding one sounds like an excellent idea, especially since that will also provide Oracle compatibility (based on your chart, I haven't used Oracle in over 20 years).

I'll re-open and mark this as an enhancement opportunity.

@borisdj borisdj changed the title Binary order for Postesql or Sqlite what Provider or Strategy to use. Binary order for PostgreSql or Sqlite what Provider or Strategy to use. Jul 29, 2019
@borisdj borisdj changed the title Binary order for PostgreSql or Sqlite what Provider or Strategy to use. Binary order for PostgreSql and Sqlite what Provider or Strategy to use. Jul 29, 2019
@fubar-coder
Copy link

fubar-coder commented Feb 1, 2022

I created a GIST with the original articles converted to Markdown, because the original article isn't available anymore: https://gist.github.com/fubar-coder/393cb9d41db707bd8730df0bd2a92d06

fubar-coder added a commit to fubar-coder/RT.Comb that referenced this issue Feb 1, 2022
It's used for Oracle and SQLite (with binary UUIDs), according to issue richardtallent#12.
@fubar-coder fubar-coder linked a pull request Feb 1, 2022 that will close this issue
@marchy
Copy link

marchy commented Nov 20, 2023

Did you ever end up creating a Binary provider to support Sqlite?

We do all our new feature development on Sqlite until the model stabilizes (faster iteration as there is no need for migrations etc.), and only in the last stretch add the migrations and indexes needed for full DB persistence (MSSQL, Postgres etc.) etc.

Would be great to have the third provider added to support the trio of SQLite/Postgres/MSSQL out of the box.

@richardtallent
Copy link
Owner

richardtallent commented Nov 21, 2023

I'm open to it, if someone can do the work in the form of a PR with tests.

I've barely ever touched sqlite, and don't have the free time currently to dump into what it would take to add and test another provider.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants