Question:
I have a function that searches ODBC escape sequences, and then recursively replaces them with their native equivalent.
For example, given an ODBC escape sequence like: {fn concat(column1, column2)}
I replace it with its native SQL equivalent like this
if (StringComparer.OrdinalIgnoreCase.Equals("concat", strFunctionName)) {
strArguments = strArguments;
string[] astrArguments = strArguments.Split(',');
string strTerm = astrArguments[0] + " || " + astrArguments[1];
return strTerm;
}
Which yields column1 || column2 (PostGreSql syntax)
Generally speaking, I have to resolve the string "arglist_comma_separated" in {fn whatever(arglist_comma_separated)}
into its components
Needless to say, that with my current version, it doesn't work if argument 1 in arglist is something like
'hello, world'
Even worse, if I concat family and first name for example, it could be {fn whatever('d''Amato', 'Alberto')}
How would I best split the arguments ?
How can I do this with regex or by parsing ?
Edit:
Hmm, thought about it again, and had a splendid idea (replace '' with an escape character).
With that, the problem complexity has degraded from medium-high to trivial for a non-regex solution:
Addendum: Actually, only almost trivial, i forgot to consider function nesting in the splitting - stupid.
protected static string[] GetArguments(string strAllArguments)
{
string EscapeCharacter = System.Convert.ToChar(8).ToString();
strAllArguments = strAllArguments.Replace("''", EscapeCharacter);
bool bInString = false;
int iLastSplitAt = 0;
int iInFunction = 0;
System.Collections.Generic.List<string> lsArguments = new System.Collections.Generic.List<string>();
for (int i = 0; i < strAllArguments.Length; i++)
{
char strCurrentChar = strAllArguments[i];
if (strCurrentChar == '\'')
bInString = !bInString;
if (bInString)
continue;
if (strCurrentChar == '(')
iInFunction++;
if (strCurrentChar == ')')
iInFunction--;
if (strCurrentChar == ',')
{
if(iInFunction == 0)
{
string strExtract = strAllArguments.Substring(iLastSplitAt, i - iLastSplitAt);
strExtract = strExtract.Replace(EscapeCharacter, "''");
lsArguments.Add(strExtract);
iLastSplitAt = i;
}
}
}
string strExtractLast = strAllArguments.Substring(iLastSplitAt + 1);
strExtractLast = strExtractLast.Replace(EscapeCharacter, "''");
lsArguments.Add(strExtractLast);
string[] astrResult = lsArguments.ToArray();
lsArguments.Clear();
lsArguments = null;
return astrResult;
}