using LJLib.Method;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace LJLib.DAL.SQL
{
internal static class SqlStrHelper
{
///
/// 从查询语句中分离出字段部分与表部分
///
/// 查询语句ie:select...from...
/// 两项分别是字段部分、表部分
private static string[] SpliteSelectStr(string selectstr)
{
Regex regex = new Regex(@"\bselect\s+(distinct\s+)?(.+?)\s+from\s+(.*)", RegexOptions.IgnoreCase | RegexOptions.Singleline);
Match match = regex.Match(selectstr);
string outCmdStr = string.Empty;
if (match.Success)
{
return new[] {match.Groups[2].Value.Trim(), match.Groups[3].Value.Trim(), match.Groups[1].Value.Trim()};
}
else
{
throw new Exception("selectstr分析失败,ie:select...from...");
}
}
///
/// 分析字段部分
///
/// 字段部分
/// 字段名对字段表达式
/// 字段名对排序表达式
private static void AnalyseFields(string orgFieldStr, Dictionary orgFields, Dictionary orgOrderFields)
{
string[] selectFieldArr = SplitFields(orgFieldStr);
string[] pattens = new string[] { @"^\s*(?(?\w+))\s*=.+$", @"^.+\s+as\s+(?(?\w+))\s*$", @"^.+\s+(?(?\w+))\s*$", @"^(?.*\.\s*(?\w+)\s*)$", @"^\s*(?(?\w+))\s*$" };
foreach (string orgField in selectFieldArr)
{
var find = false;
foreach (string patten in pattens)
{
Match fiMatch = Regex.Match(orgField, patten, RegexOptions.IgnoreCase | RegexOptions.Singleline);
if (fiMatch.Success)
{
find = true;
string key = fiMatch.Groups["key"].Value.Trim().ToLower();
if (orgFields.ContainsKey(key))
{
throw new Exception(string.Format("查询字段名重复:[{0}] = [{1}]", orgFields[key], orgField));
}
orgFields[key] = fiMatch.Value.Trim();
orgOrderFields[key] = fiMatch.Groups["sort"].Value.Trim();
break;
}
}
if (!find)
{
throw new Exception(string.Format("字段表达式分析失败:{0}", orgField));
}
}
}
///
/// 将字段部分拆分
///
/// 字段部分
/// 各字段
private static string[] SplitFields(string orgFieldStr)
{
List rslt = new List();
string builder = string.Empty;
Stack states = new Stack();
for (int i = 0; i < orgFieldStr.Length; i++)
{
char cur = orgFieldStr[i];
if (states.Count == 0)
{
if (cur == ',')
{
rslt.Add(builder);
builder = string.Empty;
}
else
{
builder += cur;
if (cur == '(' || cur == '\'')
{
states.Push(cur);
}
}
}
else
{
builder += cur;
char curstate = states.Peek();
if (curstate == '\'')
{
if (cur == '\'')
{
states.Pop();
}
}
else
{
if (cur == '(' || cur == '\'')
{
states.Push(cur);
}
else if (cur == ')')
{
states.Pop();
}
}
}
}
rslt.Add(builder.Trim());
return rslt.ToArray();
}
///
/// 生成新的字段语句
///
/// 字段名-字段表达式
/// 输出字段名ie:mtrlid,mtrlname,如果与原始字段完全不匹配就输出全部字段,最终会变成与输出字段一至
/// 新的字段语句
private static string BuildSelectFields(Dictionary orgFields, ref string preOutFieldStr, string orderFieldStr = null)
{
string outFieldStr = string.Empty;
Dictionary outFields = new Dictionary();
if (!string.IsNullOrEmpty(preOutFieldStr))
{
string[] fields = preOutFieldStr.Split(',');
foreach (string field in fields)
{
string key = field.Trim().ToLower();
if (orgFields.ContainsKey(key) && !outFields.ContainsKey(key))
{
outFields[key] = orgFields[key];
}
}
}
if (!string.IsNullOrEmpty(orderFieldStr))
{
string[] fields = orderFieldStr.Split(',');
foreach (string field in fields)
{
string key = field.Trim().ToLower();
if (orgFields.ContainsKey(key) && !outFields.ContainsKey(key))
{
outFields[key] = orgFields[key];
}
}
}
preOutFieldStr = string.Empty;
if (outFields.Count == 0)
{
outFields = orgFields;
}
foreach (KeyValuePair kvp in outFields)
{
if (string.IsNullOrEmpty(outFieldStr))
{
outFieldStr = kvp.Value;
}
else
{
outFieldStr += "," + kvp.Value;
}
if (string.IsNullOrEmpty(preOutFieldStr))
{
preOutFieldStr = kvp.Key;
}
else
{
preOutFieldStr += "," + kvp.Key;
}
}
return outFieldStr;
}
///
/// 生成新的排序语名
///
/// 字段名-字段表达式
/// 输出字段名ie:mtrlid asc,mtrlname desc
/// 可为空
private static string BuildOrderFields(Dictionary orgOrderFields, string preOrderStr)
{
string outOrderStr = string.Empty;
Dictionary outOrderFields = new Dictionary();
if (!string.IsNullOrEmpty(preOrderStr))
{
string[] fields = preOrderStr.Split(',');
foreach (string field in fields)
{
string key = field.Trim().ToLower();
string[] arr = key.Split(' ');
if (arr.Length > 1)
{
key = arr[0];
string sort = arr[arr.Length - 1];
if (orgOrderFields.ContainsKey(key) && !outOrderFields.ContainsKey(key) && (sort == "asc" || sort == "desc"))
{
outOrderFields[key] = orgOrderFields[key] + " " + sort;
}
}
else
{
if (orgOrderFields.ContainsKey(key) && !outOrderFields.ContainsKey(key))
{
outOrderFields[key] = orgOrderFields[key];
}
}
}
}
foreach (KeyValuePair kvp in outOrderFields)
{
if (string.IsNullOrEmpty(outOrderStr))
{
outOrderStr = kvp.Value;
}
else
{
outOrderStr += "," + kvp.Value;
}
}
return outOrderStr;
}
///
/// 生成新的查询语句
///
/// 原始查询语名,select...from...
/// 输出字段
/// 条件语句
/// 排序语句
/// 页数
/// 每页项数
/// 新的查询语句
public static string BuildSelectStr(string orgSelectStr, ref string preOutFieldStr, string orgWhereStr,
string preOrderStr, int pageindex, int pagesize)
{
var parts = SpliteSelectStr(orgSelectStr);
var orgFieldStr = parts[0];
var orgFromStr = parts[1];
var distinctStr = parts[2];
Dictionary orgFields = new Dictionary();
Dictionary orgOrderFields = new Dictionary();
AnalyseFields(orgFieldStr, orgFields, orgOrderFields);
string outFieldStr = BuildSelectFields(orgFields, ref preOutFieldStr, preOrderStr);
string outOrderStr = BuildOrderFields(orgOrderFields, preOrderStr);
var outCmdStr = outFieldStr + " FROM " + orgFromStr;
if (!string.IsNullOrEmpty(orgWhereStr))
{
outCmdStr += " WHERE " + orgWhereStr;
}
if (!string.IsNullOrEmpty(outOrderStr))
{
outCmdStr += " ORDER BY " + outOrderStr;
}
if (pageindex > 0 && pagesize > 0)
{
outCmdStr = "SELECT " + distinctStr + " TOP " + (pageindex * pagesize).ToString() + " " + outCmdStr;
outCmdStr = "SELECT RowNumber = IDENTITY(INT,1, 1)," + preOutFieldStr + " INTO #tmp_sorttable FROM (" +
outCmdStr + @") a
SELECT TOP " + pagesize.ToString() + " " + preOutFieldStr + @" FROM #tmp_sorttable WHERE RowNumber > " +
(pagesize * (pageindex - 1)).ToString() + @" ORDER BY RowNumber
DROP TABLE #tmp_sorttable";
}
else if (pageindex <= 0 && pagesize > 0)
{
outCmdStr = "SELECT " + distinctStr + " TOP " + pagesize + " " + outCmdStr;
}
else
{
outCmdStr = "SELECT " + distinctStr + " " + outCmdStr;
}
return outCmdStr;
}
public static string RemoveComment(string source)
{
var sb = new StringBuilder();
using (StringReader reader = new StringReader(source))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains("--"))
{
int commentstart = -1;
var instr = false;
for (var i = 0; i < line.Length; i++)
{
var curchar = line[i];
if (curchar == '\'')
{
instr = !instr;
}
else if (!instr)
{
if (curchar == '-')
{
if (i + 1 < line.Length)
{
if (line[i + 1] == '-')
{
commentstart = i;
break;
}
}
}
}
}
if (commentstart >= 0)
{
line = line.Substring(0, commentstart);
}
}
sb.AppendLine(line);
}
}
return sb.ToString().TrimEnd('\n').TrimEnd('\r');
}
public static ParseResult ParseSelectStr(string orgSelectStr)
{
var rslt = new ParseResult();
orgSelectStr = RemoveComment(orgSelectStr);
var indexchars = GetIndexChar(orgSelectStr);
var regex = new Regex(@"\bselect\s+(distinct\s+)?(top\b)?", RegexOptions.IgnoreCase | RegexOptions.Singleline);
#region 查找select关键字
var selectMatch = regex.Match(orgSelectStr);
if (!selectMatch.Success)
{
throw new Exception(string.Format("查找select关键字失败,表达式[{0}],请检查:{1}", regex, orgSelectStr));
}
var stateIndex = indexchars.Keys.GetFirstIndexBefore(selectMatch.Index);
if (stateIndex >= 0)
{
throw new Exception(string.Format("第{0}个字符的select关键字前面不允许存在括号或字符串,表达式[{1}],请检查:{2}", selectMatch.Index, regex,
orgSelectStr));
}
if (!string.IsNullOrEmpty(selectMatch.Groups[2].Value))
{
throw new Exception(string.Format("第{0}位,不应该包含TOP关键字,请使用分页参数,请检查:{1}", selectMatch.Groups[2].Index,
orgSelectStr));
}
rslt.selectStr = orgSelectStr.Substring(0, selectMatch.Index + selectMatch.Length);
#endregion
regex = new Regex(@"\bfrom\b", RegexOptions.IgnoreCase | RegexOptions.Singleline);
#region 查找from关键字
var match = regex.Match(orgSelectStr);
int fromIndex = -1;
while (match.Success)
{
stateIndex = indexchars.Keys.GetFirstIndexBefore(match.Index);
if (stateIndex < 0 || indexchars.Values[stateIndex] == ' ')
{
fromIndex = match.Index;
break;
}
match = match.NextMatch();
}
if (fromIndex < 0)
{
throw new Exception(string.Format("最外层查找from字句失败,请检查:{0}", orgSelectStr));
}
#endregion
#region 分析返回字段
Dictionary orgFields = new Dictionary();
Dictionary orgOrderFields = new Dictionary();
var parts = SpliteSelectStr(orgSelectStr);
var orgFieldStr = parts[0];
AnalyseFields(orgFieldStr, orgFields, orgOrderFields);
rslt.selectFieldsDic = orgFields;
#endregion
regex = new Regex(@"\where\b", RegexOptions.IgnoreCase | RegexOptions.Singleline);
#region 查找where关键字
int whereIndex = -1;
match = regex.Match(orgSelectStr, fromIndex);
while (match.Success)
{
stateIndex = indexchars.Keys.GetFirstIndexBefore(match.Index);
if (stateIndex < 0 || indexchars.Values[stateIndex] == ' ')
{
whereIndex = match.Index;
break;
}
match = match.NextMatch();
}
#endregion
regex = new Regex(@"\bgroup\b", RegexOptions.IgnoreCase | RegexOptions.Singleline);
#region 查找group关键字
int groupIndex = -1;
match = regex.Match(orgSelectStr, fromIndex);
while (match.Success)
{
stateIndex = indexchars.Keys.GetFirstIndexBefore(match.Index);
if (stateIndex < 0 || indexchars.Values[stateIndex] == ' ')
{
groupIndex = match.Index;
break;
}
match = match.NextMatch();
}
#endregion
regex = new Regex(@"\border\b", RegexOptions.IgnoreCase | RegexOptions.Singleline);
#region 查找order关键字
int orderindex = -1;
match = regex.Match(orgSelectStr, fromIndex);
while (match.Success)
{
stateIndex = indexchars.Keys.GetFirstIndexBefore(match.Index);
if (stateIndex < 0 || indexchars.Values[stateIndex] == ' ')
{
orderindex = match.Index;
break;
}
match = match.NextMatch();
}
#endregion
rslt.fromStr = string.Empty;
var fromStopIndexs = new List { whereIndex, groupIndex, orderindex }.Where(x => x > 0);
if (fromStopIndexs.Any())
{
rslt.fromStr = orgSelectStr.Substring(fromIndex, fromStopIndexs.Min() - fromIndex);
}
else
{
rslt.fromStr = orgSelectStr.Substring(fromIndex);
}
rslt.whereStr = string.Empty;
if (whereIndex > 0)
{
var whereStopIndexs = new List { groupIndex, orderindex }.Where(x => x > 0);
if (whereStopIndexs.Any())
{
rslt.whereStr = orgSelectStr.Substring(whereIndex, whereStopIndexs.Min() - whereIndex);
}
else
{
rslt.whereStr = orgSelectStr.Substring(whereIndex);
}
}
rslt.orderStr = string.Empty;
if (orderindex > 0)
{
rslt.orderStr = orgSelectStr.Substring(orderindex);
}
rslt.groupStr = string.Empty;
if (groupIndex > 0)
{
if (orderindex > 0)
{
rslt.groupStr = orgSelectStr.Substring(groupIndex, orderindex - groupIndex);
}
else
{
rslt.groupStr = orgSelectStr.Substring(groupIndex);
}
}
return rslt;
}
///
/// 获取SQL中括号与字符串的转换位置
///
///
///
public static SortedList GetIndexChar(string sqlStr)
{
var rslt = new SortedList();
Stack states = new Stack();
char curstate = ' ';
for (int i = 0; i < sqlStr.Length; i++)
{
char cur = sqlStr[i];
if (curstate == '\'')
{
if (cur == '\'')
{
states.Pop();
curstate = states.Count > 0 ? states.Peek() : ' ';
rslt[i] = curstate;
}
continue;
}
if (curstate == '(')
{
if (cur == ')')
{
states.Pop();
curstate = states.Count > 0 ? states.Peek() : ' ';
rslt[i] = curstate;
continue;
}
}
if (curstate == '[')
{
if (cur == ']')
{
states.Pop();
curstate = states.Count > 0 ? states.Peek() : ' ';
rslt[i] = curstate;
continue;
}
}
if (cur == '(' || cur == '\'' || cur == '[')
{
states.Push(cur);
curstate = cur;
rslt[i] = curstate;
continue;
}
if (cur == ')')
{
throw new Exception(string.Format("第{0}位\")\"没有找到对应的\"(\",请检查:{1}", i, sqlStr));
}
if (cur == ']')
{
throw new Exception(string.Format("第{0}位\"]\"没有找到对应的\"[\",请检查:{1}", i, sqlStr));
}
}
if (states.Count > 0)
{
throw new Exception(string.Format("第{0}位\"{1}\"没有找到对应的结束符,请检查:{2}", rslt.Keys[rslt.Count - 1], rslt.Values[rslt.Count - 1], sqlStr));
}
return rslt;
}
public class ParseResult
{
public string selectStr { get; set; }
//public List selectFields { get; set; }
//public List selectTitles { get; set; }
public Dictionary selectFieldsDic { get; set; }
public string fromStr { get; set; }
public string whereStr { get; set; }
public string groupStr { get; set; }
public string orderStr { get; set; }
}
}
}