|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using searchComponent.structure;
using searchComponent.grammar;
using Irony.Parsing;
namespace searchComponent.interpreter
{
/// <summary>
/// This class is responsible for converting the search query string into a valid
/// sql query string.
/// </summary>
public class SqlServerInterpreter
{
private static readonly ILog log = LogManager.GetLogger("Standard");
#region Fields
/// <summary>
/// This is the structure base for which the interpreter will construct the sql query.
/// </summary>
private SearchStructure _structure;
#endregion
#region Constructor
/// <summary>
/// Constructor, only needs the structure.
/// </summary>
public SqlServerInterpreter(SearchStructure objStructure)
{
this._structure = objStructure;
}
#endregion
#region Public Methods
/// <summary>
/// This method gets the query for SQLServer
/// </summary>
/// <param name="objColumn"></param>
/// <param name="numericQuery"></param>
/// <returns></returns>
public string GetQuery(string aQuery)
{
FieldGrammar grammar = new FieldGrammar(_structure);
LanguageData language = new LanguageData(grammar);
Parser parser = new Parser(language);
ParseTree parseTree = parser.Parse(aQuery);
if (parseTree.Status == ParseTreeStatus.Error)
{
string messages = "";
ParserMessageList listMessages = parseTree.ParserMessages;
foreach(ParserMessage objMsg in listMessages) {
messages += objMsg.Message + "\n";
}
throw new Exception(messages);
}
ParseTreeNode root = parseTree.Root;
StringBuilder query = new StringBuilder();
query.Append(GetColumnsAndFrom());
query.Append(" WHERE ");
query.Append(ConvertQuery(root));
return query.ToString();
}
/// <summary>
/// Returns a list of possible suggestions for the query given accoding to the
/// structure contained in this object.
/// It parses the query and searches for the Expected Terms value.
/// Then, depending on the column calls the method GetSuggestion for the
/// corresponding grammar.
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
public List<SuggestLine> GetSuggestion(string aQuery)
{
FieldGrammar grammar = new FieldGrammar(_structure);
LanguageData language = new LanguageData(grammar);
Parser parser = new Parser(language);
ParseTree parseTree = parser.Parse(aQuery);
StringSet expectedTerms = parser.Context.GetExpectedTermSet();
return new List<SuggestLine>();
}
#endregion
#region Private Methods
/// <summary>
/// This method obtains the select col1, col2, etc from tbl1 left|right|inner join tblx on
/// part of the sql query.
/// </summary>
/// <returns></returns>
private string GetColumnsAndFrom()
{
StringBuilder result = new StringBuilder("SELECT ");
foreach (TableStructure tbl in _structure.Tables)
{
foreach (Column col in tbl.Columns)
{
if (col.AppearInResults)
{
result.Append(col.FullName + " AS " + col.Title + ", ");
}
}
}
result.Remove(result.Length - 2, 2);
result.Append(" FROM " + _structure.Tables[0].Name);
for (int i = 1; i < _structure.Tables.Count; i++ )
{
TableStructure tbl = _structure.Tables[i];
result.Append(tbl.GetJoinQuery());
}
return result.ToString();
}
/// <summary>
/// Returns the string containing the sql Query corresponding to this ParseTreenode
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
private string ConvertQuery(ParseTreeNode node)
{
string result = "";
// Note that some NonTerminals don't actually get into the AST tree,
// because of some Irony's optimizations - punctuation stripping and
// node bubbling. For example, ParenthesizedExpression - parentheses
// symbols get stripped off as punctuation, and child expression node
// (parenthesized content) replaces the parent ParExpr node (the
// child is "bubbled up").
switch (node.Term.Name)
{
case "Expression":
if (node.ChildNodes.Count == 1)
{
result += ConvertQuery(node.ChildNodes[0]);
}
else
{
result += "( " + ConvertQuery(node.ChildNodes[0]) + " )";
result += " " + GetOperator(node.ChildNodes[1].ChildNodes[0].ChildNodes[0].Token.Text) + " ";
result += ConvertQuery(node.ChildNodes[2]) + "\n";
}
break;
case "ColumnSearch":
Column objColumn = this._structure.GetColumnBySearchKey(node.ChildNodes[0].Token.Text);
ColumnInterpreter objInterpreter = ColumnInterpreter.GetColumnInterpreter(objColumn);
result += objInterpreter.GetWhereQuery(node.ChildNodes[2].Token.Text);
break;
// This should never happen, even if input string is garbage
default:
result += ". Please investigate.";
break;
}
return result;
}
/// <summary>
/// Returns the correspondent operator in sql
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
private string GetOperator(string p)
{
if (p.Equals("|")) return "OR";
if (p.Equals("&")) return "AND";
log.Warn("Could not find operator " + p);
return p;
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
just a coder. Love Java, but working on asp.net