Skip to content

Commit

Permalink
Add GEOGRAPHY support to .NET connector
Browse files Browse the repository at this point in the history
Summary:
- Replaced Geometry class in .NET connector with Geography and GeographyPoint classes.
- Updated tests

Test Plan:
https://app.circleci.com/pipelines/github/memsql/SingleStoreNETConnector/210/workflows/1c547389-7892-49eb-97da-954479ad8b0d

upd: https://app.circleci.com/pipelines/github/memsql/SingleStoreNETConnector/213/workflows/9ea7ffea-72eb-4e0d-8fec-c35afbed5c1c

Reviewers: pmishchenko-ua

Reviewed By: pmishchenko-ua

Subscribers: engineering-list

JIRA Issues: PLAT-6084

Differential Revision: https://grizzly.internal.memcompute.com/D56606
  • Loading branch information
okramarenko committed May 20, 2022
1 parent 301ebd9 commit f872e4e
Show file tree
Hide file tree
Showing 36 changed files with 446 additions and 186 deletions.
12 changes: 6 additions & 6 deletions SingleStoreNETConnector.sln
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ VisualStudioVersion = 15.0.27130.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SingleStoreConnector", "src\SingleStoreConnector\SingleStoreConnector.csproj", "{F82378AF-274E-4FBA-8E45-27126D607B85}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SingleStoreConnector.Tests", "tests\SingleStoreConnector.Tests\SingleStoreConnector.Tests.csproj", "{5E4FF768-D007-4D66-8220-AE789CC614C2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SideBySide", "tests\SideBySide\SideBySide.csproj", "{407C2AC9-0CCA-4D6B-8698-362976D97730}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Conformance.Tests", "tests\Conformance.Tests\Conformance.Tests.csproj", "{CC0DA702-43E8-471E-9320-F36685C540A1}"
Expand All @@ -20,6 +18,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SingleStoreConnector.Loggin
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SingleStoreConnector.Authentication.Ed25519", "src\SingleStoreConnector.Authentication.Ed25519\SingleStoreConnector.Authentication.Ed25519.csproj", "{5DB4FA2E-910B-47CE-B467-F6852104D567}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SingleStoreConnector.Tests", "tests\SingleStoreConnector.Tests\SingleStoreConnector.Tests.csproj", "{7A89FC1F-4DD2-4D84-A489-57BE246A1FB8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -30,10 +30,6 @@ Global
{F82378AF-274E-4FBA-8E45-27126D607B85}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F82378AF-274E-4FBA-8E45-27126D607B85}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F82378AF-274E-4FBA-8E45-27126D607B85}.Release|Any CPU.Build.0 = Release|Any CPU
{5E4FF768-D007-4D66-8220-AE789CC614C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E4FF768-D007-4D66-8220-AE789CC614C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E4FF768-D007-4D66-8220-AE789CC614C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E4FF768-D007-4D66-8220-AE789CC614C2}.Release|Any CPU.Build.0 = Release|Any CPU
{407C2AC9-0CCA-4D6B-8698-362976D97730}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{407C2AC9-0CCA-4D6B-8698-362976D97730}.Debug|Any CPU.Build.0 = Debug|Any CPU
{407C2AC9-0CCA-4D6B-8698-362976D97730}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -62,6 +58,10 @@ Global
{5DB4FA2E-910B-47CE-B467-F6852104D567}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DB4FA2E-910B-47CE-B467-F6852104D567}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DB4FA2E-910B-47CE-B467-F6852104D567}.Release|Any CPU.Build.0 = Release|Any CPU
{7A89FC1F-4DD2-4D84-A489-57BE246A1FB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7A89FC1F-4DD2-4D84-A489-57BE246A1FB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7A89FC1F-4DD2-4D84-A489-57BE246A1FB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7A89FC1F-4DD2-4D84-A489-57BE246A1FB8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
3 changes: 2 additions & 1 deletion docs/content/api/SingleStoreConnector.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion docs/content/api/SingleStoreConnector/SingleStoreDbType.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions docs/content/api/SingleStoreConnector/SingleStoreGeography.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions docs/content/api/SingleStoreConnector/SingleStoreGeographyPoint.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 12 additions & 4 deletions src/SingleStoreConnector/Core/BinaryRow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,17 @@ protected override object GetValueCore(ReadOnlySpan<byte> data, ColumnDefinition
return ReadBit(data, columnDefinition);

case ColumnType.String:
if (Connection.GuidFormat == SingleStoreGuidFormat.Char36 && columnDefinition.ColumnLength / ProtocolUtility.GetBytesPerCharacter(columnDefinition.CharacterSet) == 36)
var columnLen = columnDefinition.ColumnLength /
ProtocolUtility.GetBytesPerCharacter(columnDefinition.CharacterSet);

if (Connection.GuidFormat == SingleStoreGuidFormat.Char36 && columnLen == 36)
return Utf8Parser.TryParse(data, out Guid guid, out int guid36BytesConsumed, 'D') && guid36BytesConsumed == 36 ? guid : throw new FormatException();
if (Connection.GuidFormat == SingleStoreGuidFormat.Char32 && columnDefinition.ColumnLength / ProtocolUtility.GetBytesPerCharacter(columnDefinition.CharacterSet) == 32)
if (Connection.GuidFormat == SingleStoreGuidFormat.Char32 && columnLen == 32)
return Utf8Parser.TryParse(data, out Guid guid, out int guid32BytesConsumed, 'N') && guid32BytesConsumed == 32 ? guid : throw new FormatException();
if (Connection.TreatChar48AsGeographyPoint && columnLen == 48)
goto case ColumnType.GeographyPoint;
if (columnLen == 1431655765)
goto case ColumnType.Geography;
goto case ColumnType.VarString;

case ColumnType.VarString:
Expand Down Expand Up @@ -148,8 +155,9 @@ protected override object GetValueCore(ReadOnlySpan<byte> data, ColumnDefinition
case ColumnType.NewDecimal:
return Utf8Parser.TryParse(data, out decimal decimalValue, out int bytesConsumed) && bytesConsumed == data.Length ? decimalValue : throw new FormatException();

case ColumnType.Geometry:
return data.ToArray();
case ColumnType.GeographyPoint:
case ColumnType.Geography:
return Encoding.UTF8.GetString(data);

default:
throw new NotImplementedException("Reading {0} not implemented".FormatInvariant(columnDefinition.ColumnType));
Expand Down
3 changes: 3 additions & 0 deletions src/SingleStoreConnector/Core/ConnectionSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ public ConnectionSettings(SingleStoreConnectionStringBuilder csb)
IgnoreCommandTransaction = csb.IgnoreCommandTransaction;
IgnorePrepare = csb.IgnorePrepare;
InteractiveSession = csb.InteractiveSession;
TreatChar48AsGeographyPoint = csb.TreatChar48AsGeographyPoint;
GuidFormat = GetEffectiveGuidFormat(csb.GuidFormat, csb.OldGuids);
Keepalive = csb.Keepalive;
NoBackslashEscapes = csb.NoBackslashEscapes;
Expand Down Expand Up @@ -227,6 +228,7 @@ private static SingleStoreGuidFormat GetEffectiveGuidFormat(SingleStoreGuidForma
public DateTimeKind DateTimeKind { get; }
public int DefaultCommandTimeout { get; }
public bool ForceSynchronous { get; }
public bool TreatChar48AsGeographyPoint { get; }
public SingleStoreGuidFormat GuidFormat { get; }
public bool IgnoreCommandTransaction { get; }
public bool IgnorePrepare { get; }
Expand Down Expand Up @@ -314,6 +316,7 @@ private ConnectionSettings(ConnectionSettings other, string host, int port, stri
IgnoreCommandTransaction = other.IgnoreCommandTransaction;
IgnorePrepare = other.IgnorePrepare;
InteractiveSession = other.InteractiveSession;
TreatChar48AsGeographyPoint = other.TreatChar48AsGeographyPoint;
GuidFormat = other.GuidFormat;
Keepalive = other.Keepalive;
NoBackslashEscapes = other.NoBackslashEscapes;
Expand Down
5 changes: 4 additions & 1 deletion src/SingleStoreConnector/Core/ISingleStoreCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public static StatementPreparerOptions CreateStatementPreparerOptions(this ISing
{
var connection = command.Connection!;
var statementPreparerOptions = StatementPreparerOptions.None;
if (connection.AllowUserVariables || command.CommandType == CommandType.StoredProcedure || command.AllowUserVariables)
if (connection.AllowUserVariables || command.CommandType == CommandType.StoredProcedure ||
command.AllowUserVariables)
statementPreparerOptions |= StatementPreparerOptions.AllowUserVariables;
if (connection.DateTimeKind == DateTimeKind.Utc)
statementPreparerOptions |= StatementPreparerOptions.DateTimeUtc;
Expand All @@ -36,6 +37,8 @@ public static StatementPreparerOptions CreateStatementPreparerOptions(this ISing
statementPreparerOptions |= StatementPreparerOptions.AllowOutputParameters;
if (connection.NoBackslashEscapes)
statementPreparerOptions |= StatementPreparerOptions.NoBackslashEscapes;
if (connection.TreatChar48AsGeographyPoint)
statementPreparerOptions |= StatementPreparerOptions.TreatChar48AsGeographyPoint;

statementPreparerOptions |= connection.GuidFormat switch
{
Expand Down
2 changes: 1 addition & 1 deletion src/SingleStoreConnector/Core/ResultSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static int ReadColumnCount(ReadOnlySpan<byte> span)

var columnDefinition = ColumnDefinitionPayload.Create(new ResizableArraySegment<byte>(m_columnDefinitionPayloads, m_columnDefinitionPayloadUsedBytes, payloadLength));
ColumnDefinitions[column] = columnDefinition;
ColumnTypes[column] = TypeMapper.ConvertToSingleStoreDbType(columnDefinition, treatTinyAsBoolean: Connection.TreatTinyAsBoolean, guidFormat: Connection.GuidFormat);
ColumnTypes[column] = TypeMapper.ConvertToSingleStoreDbType(columnDefinition, treatTinyAsBoolean: Connection.TreatTinyAsBoolean, treatChar48AsGeographyPoint: Connection.TreatChar48AsGeographyPoint, guidFormat: Connection.GuidFormat);
m_columnDefinitionPayloadUsedBytes += payloadLength;
}

Expand Down
18 changes: 12 additions & 6 deletions src/SingleStoreConnector/Core/Row.cs
Original file line number Diff line number Diff line change
Expand Up @@ -422,14 +422,21 @@ public SingleStoreDateTime GetSingleStoreDateTime(int ordinal)
return (SingleStoreDateTime) value;
}

public SingleStoreGeometry GetSingleStoreGeometry(int ordinal)
public SingleStoreGeography GetSingleStoreGeography(int ordinal)
{
var value = GetValue(ordinal);
if (value is byte[] bytes && ResultSet.ColumnDefinitions![ordinal].ColumnType == ColumnType.Geometry)
return new SingleStoreGeometry(bytes);
throw new InvalidCastException("Can't convert {0} to SingleStoreGeometry.".FormatInvariant(ResultSet.ColumnDefinitions![ordinal].ColumnType));
if (value is string wkt)
return new SingleStoreGeography(wkt);
return (SingleStoreGeography) value;
}

public SingleStoreGeographyPoint GetSingleStoreGeographyPoint(int ordinal)
{
var value = GetValue(ordinal);
if (value is string wkt)
return new SingleStoreGeographyPoint(wkt);
return (SingleStoreGeographyPoint) value;
}
public SingleStoreDecimal GetSingleStoreDecimal(int ordinal)
{
if (IsDBNull(ordinal))
Expand Down Expand Up @@ -599,8 +606,7 @@ private void CheckBinaryColumn(int ordinal)
var columnType = column.ColumnType;
if ((column.ColumnFlags & ColumnFlags.Binary) == 0 ||
(columnType != ColumnType.String && columnType != ColumnType.VarString && columnType != ColumnType.TinyBlob &&
columnType != ColumnType.Blob && columnType != ColumnType.MediumBlob && columnType != ColumnType.LongBlob &&
columnType != ColumnType.Geometry))
columnType != ColumnType.Blob && columnType != ColumnType.MediumBlob && columnType != ColumnType.LongBlob))
{
throw new InvalidCastException("Can't convert {0} to bytes.".FormatInvariant(columnType));
}
Expand Down
1 change: 1 addition & 0 deletions src/SingleStoreConnector/Core/StatementPreparerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ internal enum StatementPreparerOptions
GuidFormatLittleEndianBinary16 = 0xA0,
GuidFormatMask = 0xE0,
NoBackslashEscapes = 0x100,
TreatChar48AsGeographyPoint = 0x200,
}
Loading

0 comments on commit f872e4e

Please sign in to comment.