DarkWanderer / ClickHouse.Client

.NET client for ClickHouse
MIT License
302 stars 58 forks source link

Insert two fields with the common prefix #473

Closed topalach closed 2 months ago

topalach commented 2 months ago

When inserting two fields, with the second one having the same name with a suffix (e.g. Field and FieldWithSuffix), the insert fails.

Here's the test that reproduces the problem:

[Test]
public async Task ShouldWriteTwoFieldsWithTheSamePrefix()
{
    await connection.ExecuteStatementAsync("TRUNCATE TABLE IF EXISTS test.dapper_prefixes");
    await connection.ExecuteStatementAsync("CREATE TABLE IF NOT EXISTS test.dapper_prefixes (testField Int32, testFieldWithSuffix Int32) ENGINE Memory");

    const string sql = "INSERT INTO test.dapper_prefixes (testField, testFieldWithSuffix) VALUES (@testField, @testFieldWithSuffix)";
    await connection.ExecuteAsync(sql, new { testField = 1, testFieldWithSuffix = 2 });
}

and the exception:

ClickHouse.Client.ClickHouseServerException : Code: 62. DB::Exception: Cannot parse expression of type Int32 here: {testField:Int32}WithSuffix): While executing ValuesBlockInputFormat. (SYNTAX_ERROR) (version 23.7.5.30 (official build))

   at ClickHouse.Client.ADO.ClickHouseConnection.HandleError(HttpResponseMessage response, String query, Activity activity) in C:\src\trivec\forks\ClickHouse.Client\ClickHouse.Client\ADO\ClickHouseConnection.cs:line 216
   at ClickHouse.Client.ADO.ClickHouseCommand.PostSqlQueryAsync(String sqlQuery, CancellationToken token) in C:\src\trivec\forks\ClickHouse.Client\ClickHouse.Client\ADO\ClickHouseCommand.cs:line 191
   at ClickHouse.Client.ADO.ClickHouseCommand.ExecuteNonQueryAsync(CancellationToken cancellationToken) in C:\src\trivec\forks\ClickHouse.Client\ClickHouse.Client\ADO\ClickHouseCommand.cs:line 75
   at Dapper.SqlMapper.ExecuteImplAsync(IDbConnection cnn, CommandDefinition command, Object param) in /_/Dapper/SqlMapper.Async.cs:line 662
   at ClickHouse.Client.Tests.ORM.DapperTests.ShouldWriteTwoFieldsWithTheSamePrefix() in C:\src\trivec\forks\ClickHouse.Client\ClickHouse.Client.Tests\ORM\DapperTests.cs:line 206
   at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.BlockUntilCompleted()
   at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaiter)
   at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
   at NUnit.Framework.Internal.Execution.SimpleWorkItem.<>c__DisplayClass4_0.<PerformWork>b__0()
   at NUnit.Framework.Internal.ContextUtils.<>c__DisplayClass1_0`1.<DoIsolated>b__0(Object _)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at NUnit.Framework.Internal.ContextUtils.DoIsolated(ContextCallback callback, Object state)
   at NUnit.Framework.Internal.ContextUtils.DoIsolated[T](Func`1 func)
   at NUnit.Framework.Internal.Execution.SimpleWorkItem.PerformWork()
DarkWanderer commented 2 months ago

I knew the simple "replace string" approach was going to be problematic. Thank you for detailed report with test.

Releasing the fix for this as v7.4.1