Разработка языка запросов в бинарной модели знаний и транслятора этого языка в язык SQL (бакалаврская работа) (544460), страница 12
Текст из файла (страница 12)
{
return oclass;
}
}
public List<string> NeededAttributes
{
get
{
return neededAttributes;
}
}
public List<string> SimpleAttributes
{
get
{
return simpleAttributes;
}
}
public List<string> SimpleAttributeOperators
{
get
{
return simpleAttributeOperators;
}
}
public List<string> SimpleAttributeValues
{
get
{
return simpleAttributeValues;
}
}
public List<string> ComplexAttributes
{
get
{
return complexAttributes;
}
}
public List<string> ClassAttributes
{
get
{
return classAttributes;
}
}
public List<QueryVariable> ClassVariables
{
get
{
return classVariables;
}
}
}
/// <summary>
/// Класс, описывающий отношение.
/// </summary>
class Relation
{
public Relation()
{ }
public Relation(QueryVariable q1, QueryVariable q2, QueryVariable q3)
{
Left = q1;
RelVar = q2;
Right = q3;
}
public QueryVariable Left
{ get; set; }
public QueryVariable RelVar
{ get; set; }
public QueryVariable Right
{ get; set; }
public QueryVariable this[int i]
{
get
{
if (i == 0)
return Left;
if (i == 1)
return RelVar;
return Right;
}
}
}
class AttrPair
{
public QueryVariable qv1;
public string attr1;
public string attrOperator;
public QueryVariable qv2;
public string attr2;
public AttrPair(QueryVariable q1, string a1, string oper, QueryVariable q2, string a2)
{
qv1 = q1;
attr1 = a1;
attrOperator = oper;
qv2 = q2;
attr2 = a2;
}
}
static string[] operators = new string[] { "<=",">=","=","LIKE"};
static string[] aggregateFunctions = new string[] {"AVG","SUM","COUNT","MAX","MIN"};
#region Переменные
string query;
int artificialVarsCount;
string SQLquery;
string select;
string[] selectParts;
string condition;
List<QueryVariable> goalVariables;
string aggregateFunction;
List<QueryVariable> variables;
List<Relation> RelationVars;
List<AttrPair> AttrPairs;
OnthologyScheme scheme;
#endregion
#region Конструктор
public Translator(OnthologyScheme _scheme)
{
scheme = _scheme;
QueryVariable.scheme = scheme;
}
public string translate(string _query)
{
query = _query.Trim().Replace("\r\n", "");
goalVariables = new List<QueryVariable>();
variables = new List<QueryVariable>();
RelationVars = new List<Relation>();
AttrPairs = new List<AttrPair>();
artificialVarsCount = 0;
if (query == "")
{
throw new TranslatorException("Запрос пуст");
}
else if (query[0] != '?')
{
throw new TranslatorException("В начале запроса должен стоять вопросительный знак");
}
else
{
query = query.Substring(1, query.Length - 1);
divideQuery(query);
GoalProcessing();
ConditionsProcessing();
checkVariablesClass();
removeUselessVariables();
return CreateSQLQuery(query);
}
}
#endregion
void divideQuery(string query)
{
int hyphenPosition = 0;
bool hyphenIsInQuery = false;
for (int i = 0; i < query.Length; i++)
{
if (query[i] == '-')
{
hyphenPosition = i;
hyphenIsInQuery = true;
break;
}
}
if (!hyphenIsInQuery)
throw new TranslatorException("Отсутвует знак /'-/'");
if (query.Contains(" __"))
throw new TranslatorException("Нельзя использовать символы \"__\" в начале слова");
select = query.Substring(0,hyphenPosition).Trim();
condition = query.Substring(hyphenPosition + 1).Trim();
if (select == "")
throw new TranslatorException("Отсутсвует целевая переменная(выражение перед знаком /'-/')");
if (condition == "")
throw new TranslatorException("Отсутсвуют условия (выражения после знака /'-/')");
select = select.Trim();
condition = condition.Trim();
}
void GoalProcessing()
{
selectParts = select.Split(',');
QueryVariable qv = new QueryVariable("");
bool aggrFuncIsInSelect = false;
for (int i = 0; i < selectParts.Length; i++)
{
string s = selectParts[i].Trim();
if (s.Trim() == "")
{
if (i == 0)
throw new TranslatorException("Лишняя запятая после первой цели запроса " + select);
else
throw new TranslatorException("Лишняя запятая после цели " + selectParts[i - 1]);
}
int bracketPostion = s.IndexOf("(");
if (bracketPostion != -1)
{
if (!s.EndsWith(")"))
throw new TranslatorException("Незакрытая скобка в цели запроса " + s);
aggregateFunction = s.Substring(0, bracketPostion);
s = s.Substring(bracketPostion+1, s.Length - bracketPostion -2);
if (!aggregateFunctions.Contains(aggregateFunction))
throw new TranslatorException("Неизвестная функция \"" + aggregateFunction + "\" в цели запроса " + s);
aggrFuncIsInSelect = true;
}
string varName;
string attrName;
string[] goalVarParts = s.Split('.');
int lastDot = s.LastIndexOf('.');
if (goalVarParts.Length >= 3)
{
varName = "__" + artificialVarsCount;
artificialVarsCount++;
condition += ";" + s.Substring(0, lastDot) + "=" + varName;
s = varName + "." + goalVarParts[goalVarParts.Length - 1];
}
if (s.IndexOf('.') == -1)
{
varName = s;
attrName = "id";
}
else
{
varName = s.Split('.')[0];
attrName = s.Split('.')[1];
}
if (qv.Name != varName)
{
if (qv.Name != "")
{
goalVariables.Add(qv);
variables.Add(qv);
}
qv = new QueryVariable(varName);
qv.AddNeededAttribute(attrName);
}
else
{
qv.AddNeededAttribute(attrName);
}
}
goalVariables.Add(qv);
variables.Add(qv);
if (aggrFuncIsInSelect && selectParts.Length >= 2)
throw new TranslatorException("В запросе можно использовать только одну цель, если используется аггрегатная функция");
}
void ConditionsProcessing()
{
List<string> conjParts = new List<string>();
bool inBrackets = false;
string conjuctS = "";
int conjuctNumber = 0;
for (int i = 0; i < condition.Length; i++)
{
if (inBrackets && condition[i] == '(')
throw new TranslatorException("Лишняя открывающяя скобка на "+ i +" символе");
if (!inBrackets && condition[i] == ')')
throw new TranslatorException("Лишняя закрывающяя скобка на " + i + " символе");
if (condition[i] == '(')
inBrackets = true;
if (inBrackets && condition[i] == ')')
inBrackets = false;
if (!inBrackets && condition[i] ==';')
{
conjuctNumber++;
if (conjuctS.Trim() == "")
throw new TranslatorException("Конъюнктивное выражение под номером " + conjuctNumber + " пусто ( возможно лишний символ \";\")");
conjParts.Add(conjuctS.Trim());
conjuctS = "";
continue;
}
conjuctS += condition[i];
}
if (conjuctS.Trim() == "")
throw new TranslatorException("Последнее конъюнктивное выражение пусто ( возможно лишний символ \";\")");
conjParts.Add(conjuctS.Trim());
int k;
string varName;
string attrName;
string className;
List<string> conditionParts = new List<string>();
for (int i = 0; i < conjParts.Count; i++)
{
string s = conjParts[i].Trim();
#region Обработка типа
int inPosition = s.IndexOf(" IN ");
if (inPosition >= 0)
{
string typeS = s;
varName = typeS.Substring(0, inPosition).Trim();
int bracketPosition = s.IndexOf("(");
if (bracketPosition >= 0)
{
if (bracketPosition <= inPosition)
throw new TranslatorException("При использовании ключевого слова \"IN\" скобка должна стоять после имени класса");
if (!s.EndsWith(")"))
throw new TranslatorException("Отсутствует закрывающяя скобка");
typeS = s.Substring(0, bracketPosition).Trim();
string bracketS = s.Substring(bracketPosition+1,s.Length - bracketPosition - 2).Trim();
if (bracketS == "")
throw new TranslatorException("Пустое выражение внутри скобок в выражении " + s);
string[] sInBrackets = bracketS.Split(';');
conjParts.RemoveAt(i);
for (int j = sInBrackets.Length - 1; j >= 0; j--)
{
conjParts.Insert(i, varName + "." + sInBrackets[j]);
}
i--;
}
className = typeS.Substring(inPosition + 4).Trim();
k = scheme.Classes.FindIndex(cl => cl.Name == className);
if (k == -1)
{
k = scheme.Relations.FindIndex(rel => rel.Name == className);
if (k == -1)
throw new TranslatorException("Неизвестный класс: " + className + " в условии \"" + s + "\"");
}
k = variables.FindIndex(v => v.Name == varName);
if (k == -1)
variables.Add(new QueryVariable(varName,className));
else
variables[k].AddClass(className);
continue;
}
#endregion
#region Обработка отношения
int openBracketPosition = s.IndexOf('(');
if (openBracketPosition == 0)
{
if (!s.EndsWith(")"))
{
throw new TranslatorException("Отсутствует закрывающяя скобка");
}
string[] RelationParts = s.Substring(1, s.Length - 2).Split(' ');
for (int j = 0; j < RelationParts.Length; j++)
{
RelationParts[i] = RelationParts[i].Trim();
}
if (RelationParts.Length != 4 && RelationParts.Length != 3)
throw new TranslatorException("Отношение должно состоять из 4 слов:(X RelationName L Y) или из 3: (X RelationName Y)");
QueryVariable relVar;
QueryVariable leftVar;
QueryVariable rightVar;
if (RelationParts.Length == 3)
{
varName = "__" + artificialVarsCount;
artificialVarsCount++;
}
else
{
varName = RelationParts[2].Trim();
}
className = RelationParts[1].Trim();
int relIndex = scheme.Relations.FindIndex(rel => rel.Name == className);
if (relIndex == -1)
throw new TranslatorException("Переменная отношения" + varName + " относится к неизвестному отношению " + className);
string leftClassName = scheme.Relations[relIndex].Left.Name;
string rightClassName = scheme.Relations[relIndex].Right.Name;
#region Переменная отношения
k = variables.FindIndex(v => v.Name == varName);
if (k >= 0)
{
relVar = variables[k];
relVar.AddClass(className);
}
else
{
relVar = new QueryVariable(varName, className);
variables.Add(relVar);
}
#endregion
#region Левая переменная отношения
varName = RelationParts[0];
k = variables.FindIndex(v => v.Name == varName);
if (k >= 0)
{
leftVar = variables[k];
leftVar.AddClass(leftClassName);
}
else















