|
5 | 5 | using System.Diagnostics;
|
6 | 6 | using System.Diagnostics.CodeAnalysis;
|
7 | 7 | using System.IO;
|
| 8 | +using System.Text; |
8 | 9 | using MySqlConnector.Core;
|
9 | 10 | using MySqlConnector.Protocol.Serialization;
|
10 | 11 | using MySqlConnector.Utilities;
|
@@ -218,17 +219,25 @@ internal void AppendSqlString(ByteBufferWriter writer, StatementPreparerOptions
|
218 | 219 | ReadOnlySpan<byte> nullBytes = new byte[] { 0x4E, 0x55, 0x4C, 0x4C }; // NULL
|
219 | 220 | writer.Write(nullBytes);
|
220 | 221 | }
|
| 222 | +#if NET45 || NETSTANDARD1_3 |
221 | 223 | else if (Value is string stringValue)
|
222 | 224 | {
|
223 |
| - writer.Write((byte) '\''); |
224 |
| - |
225 |
| - if (noBackslashEscapes) |
226 |
| - writer.Write(stringValue.Replace("'", "''")); |
227 |
| - else |
228 |
| - writer.Write(stringValue.Replace("\\", "\\\\").Replace("'", "''")); |
229 |
| - |
230 |
| - writer.Write((byte) '\''); |
| 225 | + WriteString(writer, noBackslashEscapes, stringValue); |
| 226 | + } |
| 227 | +#else |
| 228 | + else if (Value is string stringValue) |
| 229 | + { |
| 230 | + WriteString(writer, noBackslashEscapes, writeDelimiters: true, stringValue.AsSpan()); |
| 231 | + } |
| 232 | + else if (Value is ReadOnlyMemory<char> readOnlyMemoryChar) |
| 233 | + { |
| 234 | + WriteString(writer, noBackslashEscapes, writeDelimiters: true, readOnlyMemoryChar.Span); |
| 235 | + } |
| 236 | + else if (Value is Memory<char> memoryChar) |
| 237 | + { |
| 238 | + WriteString(writer, noBackslashEscapes, writeDelimiters: true, memoryChar.Span); |
231 | 239 | }
|
| 240 | +#endif |
232 | 241 | else if (Value is char charValue)
|
233 | 242 | {
|
234 | 243 | writer.Write((byte) '\'');
|
@@ -398,6 +407,19 @@ internal void AppendSqlString(ByteBufferWriter writer, StatementPreparerOptions
|
398 | 407 | writer.Advance(guidLength);
|
399 | 408 | }
|
400 | 409 | }
|
| 410 | + else if (Value is StringBuilder stringBuilder) |
| 411 | + { |
| 412 | +#if NETCOREAPP3_1 || NET5_0 |
| 413 | + writer.Write((byte) '\''); |
| 414 | + foreach (var chunk in stringBuilder.GetChunks()) |
| 415 | + WriteString(writer, noBackslashEscapes, writeDelimiters: false, chunk.Span); |
| 416 | + writer.Write((byte) '\''); |
| 417 | +#elif NET45 || NETSTANDARD1_3 |
| 418 | + WriteString(writer, noBackslashEscapes, stringBuilder.ToString()); |
| 419 | +#else |
| 420 | + WriteString(writer, noBackslashEscapes, writeDelimiters: true, stringBuilder.ToString().AsSpan()); |
| 421 | +#endif |
| 422 | + } |
401 | 423 | else if (MySqlDbType == MySqlDbType.Int16)
|
402 | 424 | {
|
403 | 425 | writer.WriteString((short) Value);
|
@@ -434,6 +456,52 @@ internal void AppendSqlString(ByteBufferWriter writer, StatementPreparerOptions
|
434 | 456 | {
|
435 | 457 | throw new NotSupportedException("Parameter type {0} is not supported; see https://fl.vu/mysql-param-type. Value: {1}".FormatInvariant(Value.GetType().Name, Value));
|
436 | 458 | }
|
| 459 | + |
| 460 | +#if NET45 || NETSTANDARD1_3 |
| 461 | + static void WriteString(ByteBufferWriter writer, bool noBackslashEscapes, string value) |
| 462 | + { |
| 463 | + writer.Write((byte) '\''); |
| 464 | + |
| 465 | + if (noBackslashEscapes) |
| 466 | + writer.Write(value.Replace("'", "''")); |
| 467 | + else |
| 468 | + writer.Write(value.Replace("\\", "\\\\").Replace("'", "''")); |
| 469 | + |
| 470 | + writer.Write((byte) '\''); |
| 471 | + } |
| 472 | +#else |
| 473 | + static void WriteString(ByteBufferWriter writer, bool noBackslashEscapes, bool writeDelimiters, ReadOnlySpan<char> value) |
| 474 | + { |
| 475 | + if (writeDelimiters) |
| 476 | + writer.Write((byte) '\''); |
| 477 | + |
| 478 | + var charsWritten = 0; |
| 479 | + while (charsWritten < value.Length) |
| 480 | + { |
| 481 | + var remainingValue = value.Slice(charsWritten); |
| 482 | + var nextDelimiterIndex = remainingValue.IndexOfAny('\'', '\\'); |
| 483 | + if (nextDelimiterIndex == -1) |
| 484 | + { |
| 485 | + // write the rest of the string |
| 486 | + writer.Write(remainingValue); |
| 487 | + charsWritten += remainingValue.Length; |
| 488 | + } |
| 489 | + else |
| 490 | + { |
| 491 | + // write up to (and including) the delimiter, then double it |
| 492 | + writer.Write(remainingValue.Slice(0, nextDelimiterIndex + 1)); |
| 493 | + if (remainingValue[nextDelimiterIndex] == '\\' && !noBackslashEscapes) |
| 494 | + writer.Write((byte) '\\'); |
| 495 | + else if (remainingValue[nextDelimiterIndex] == '\'') |
| 496 | + writer.Write((byte) '\''); |
| 497 | + charsWritten += nextDelimiterIndex + 1; |
| 498 | + } |
| 499 | + } |
| 500 | + |
| 501 | + if (writeDelimiters) |
| 502 | + writer.Write((byte) '\''); |
| 503 | + } |
| 504 | +#endif |
437 | 505 | }
|
438 | 506 |
|
439 | 507 | internal void AppendBinary(ByteBufferWriter writer, StatementPreparerOptions options)
|
@@ -591,6 +659,20 @@ internal void AppendBinary(ByteBufferWriter writer, StatementPreparerOptions opt
|
591 | 659 | writer.Advance(guidLength);
|
592 | 660 | }
|
593 | 661 | }
|
| 662 | +#if !NET45 && !NETSTANDARD1_3 |
| 663 | + else if (Value is ReadOnlyMemory<char> readOnlyMemoryChar) |
| 664 | + { |
| 665 | + writer.WriteLengthEncodedString(readOnlyMemoryChar.Span); |
| 666 | + } |
| 667 | + else if (Value is Memory<char> memoryChar) |
| 668 | + { |
| 669 | + writer.WriteLengthEncodedString(memoryChar.Span); |
| 670 | + } |
| 671 | +#endif |
| 672 | + else if (Value is StringBuilder stringBuilder) |
| 673 | + { |
| 674 | + writer.WriteLengthEncodedString(stringBuilder.ToString()); |
| 675 | + } |
594 | 676 | else if (MySqlDbType == MySqlDbType.Int16)
|
595 | 677 | {
|
596 | 678 | writer.Write((ushort) (short) Value);
|
|
0 commit comments