I'm working on a SQLFormat-function, that work like the normal String.Format
.
And now I'm stuck on being reliant on which index the current Format
is in.
For example, we have this SQL-query (Psuedo, not actual usage).
SELECT *
FROM users
WHERE userID = {0:SQL;userID}
AND 10 != {1:SQL;strangeID}
AND 100 = {0:SQL;userID}
This is being formatted like this right now:
SELECT *
FROM users
WHERE userID = @p0 /* userID */
AND 10 != @p1 /* strangeID */
AND 100 = @p2 /* userID */
Where it outputs @p2
, I want it to reuse @p0
(since I've already added that parameter)
Here's my class that does the formatting. Currently I'm using an static int for the indexing
I haven't found out if I can get the current parameter-index).
One way would be to skip the formatting, but I need this, so I can skip replacing the tokens myself. (I think that String.Format
is faster than code I could produce :P)
UPDATED: I have updated the code with my current code, I prepare all the tokens on beforehand and push in the parameter-names as values instead of the values.
public class SqlFormat : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
return null;
}
internal int IndexCounter = 0;
Dictionary<string, int> dict = new Dictionary<string, int>();
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (!this.Equals(formatProvider))
return null;
if (string.IsNullOrWhiteSpace(format))
format = "SQL;field";
var formats = format.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
format = formats[0];
if (format == "SQL")
{
string ind = IndexCounter.ToString();
if (dict.ContainsKey(formats[1])) ind = dict[formats[1]].ToString();
else dict.Add(formats[1], IndexCounter++);
var pName = arg;
return pName + (formats.Length > 1 ? " /* " + formats[1] + " */" : "");
}
else
{
return HandleOtherFormats(format, arg);
}
}
public string HandleOtherFormats(string format, object arg)
{
return string.Format(format, arg);
}
}
Example usage:
var sql = @"SELECT {0:SQL;userID}, {0:SQL;userID}";
var retSql = String.Format(new SqlFormat(), sql, new[] { 650 });
Console.WriteLine(retSql);
This returns SELECT @p0 /* userID */, @p1 /* userID */
instead of
SELECT @p0 /* userID */, @p0 /* userID */
Is there some way that I can get the current index? 0
in this case.
Looking at your example and running it here was an interesting lesson about stuff I hadn't seen before, so I may be completely off..
the 0
in the {0:
looks to my like the index of the placeholder to insert. Your format always has only one value, so it will always use and need only a 0
.
The internal (not static!) int is obviously nonsense. And the idea that you want to get at the current index seems wrong, too.
To me the solution would be that you either actually do provide two values, the number and the name not just the name. Can't help you with the syntax. Or, and that would be better I think, that you deduct the number from the name.
You could build a dictionary and pull the number from it, whenever you meet a name that is already in the dictionary. The other names get added with an incremented number.
Here is a quick one; seems to work..:
public class SqlFormat : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
return null;
}
internal int IndexCounter = 0;
Dictionary<string, int> dict = new Dictionary<string, int>();
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (!this.Equals(formatProvider))
return null;
if (string.IsNullOrEmpty(format))
format = "SQL";
var formats = format.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
format = formats[0];
if (format == "SQL")
{
string ind = IndexCounter.ToString();
if (dict.ContainsKey(formats[1])) ind = dict[formats[1]].ToString();
else dict.Add(formats[1], IndexCounter++);
var pName = "@p" + ind;
return pName + (formats.Length > 1 ? " /* " + formats[1] + " */" : "");
}
else
{
return HandleOtherFormats(format, arg);
}
}
public string HandleOtherFormats(string format, object arg)
{
return string.Format(format, arg);
}