|
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