Note that there are some explanatory texts on larger screens.

plurals
  1. POC# & T-SQL string[] Pack/Unpack utility functions
    primarykey
    data
    text
    <p>Can anyone skilled in t-sql create companion table-valued functions to these C# array pack &amp; unpack utility methods that escape delimiters and preserve nulls, null arrays, empty arrays through roundtrip encoding?</p> <p>By packing any variety of string arrays into a string, you can pass such (small) arrays to SQL as parameters, which is useful in some scenarios.</p> <pre><code>static class ArrayUtil { public static string Pack(string[] original) { return Pack(original, '|', '0', '~'); } public static string[] Unpack(string original) { return Unpack(original, '|', '0', '~'); } public static string Pack(string[] original, char delimiter, char zed, char escape) { if (delimiter == escape || zed == escape || delimiter == zed) throw new ArgumentException("special characters must be distinct"); // Null array returns a null string if (original == null) return null; // Empty array returns an empty string if (original.Length == 0) return string.Empty; // Arrays with a single empty element are represented as just the escape character // to differentiate from an empty array if (original.Length == 1 &amp;&amp; original[0] == string.Empty) return escape.ToString(); // Otherwise StringBuilder sb = new StringBuilder(); for (int i = 0, ol = original.Length; i &lt; ol; i++) { string s = original[i]; if (s == null) { sb.Append(zed); // zed == null } else { for (int j = 0, sl = s.Length; j &lt; sl; j++) { char c = s[j]; // escape literal delimiters, escapes, and leading zeds if (c == delimiter || c == escape || (c == zed &amp;&amp; j == 0)) sb.Append(escape); sb.Append(c); } } if (i != ol - 1) sb.Append(delimiter); // no trailing delimiter } return sb.ToString(); } public static string[] Unpack(string original, char delimiter, char zed, char escape) { if (delimiter == escape || zed == escape || delimiter == zed) throw new ArgumentException("special characters must be distinct"); // Null string returns a null array if (original == null) return null; // Empty string returns an empty array if (original == string.Empty) return new string[] { }; // A single escape character represents an array with a single empty element // to differentiate from an empty array if (original == escape.ToString()) return new string[] { string.Empty }; // Otherwise StringBuilder sb = new StringBuilder(); // A place to store the current element StringReader sr = new StringReader(original); // A stream of the original string List&lt;string&gt; unpacked = new List&lt;string&gt;(); // The finished elements int next; while ((next = sr.Read()) &gt;= 0) { char c = (char)next; if (c == zed &amp;&amp; sb.Length == 0) { unpacked.Add(null); if ((next = sr.Peek()) &gt;= 0 &amp;&amp; (char)next != delimiter) throw new ArgumentException("An element's leading zed character must be escaped or must alone be the element", "original"); sb = null; } else if (c == delimiter) { if (sb != null) unpacked.Add(sb.ToString()); sb = new StringBuilder(); } else if (c == escape) { if ((next = sr.Read()) &gt;= 0) { sb.Append((char)next); } else throw new ArgumentException("Escapee expected", "original"); } else { sb.Append(c); } } // A final zed character will make sb = null, but otherwise we have an additional element if (sb != null) unpacked.Add(sb.ToString()); return unpacked.ToArray(); } } </code></pre> <p>Example packings with <code>Pack(original, '|', '0', '~')</code>, basic case:</p> <pre><code>["hello", "world"] -&gt; "hello|world" </code></pre> <p>Some special cases (as discovered by PEX)</p> <pre><code>null -&gt; null [null] -&gt; "0" [null, null] -&gt; "0|0" [] -&gt; "" [""] -&gt; "~" ["", ""] -&gt; "|" ["|", "|"] -&gt; "~||~|" </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload