Разработка языка запросов в бинарной модели знаний и транслятора этого языка в язык SQL (бакалаврская работа) (544460), страница 13
Текст из файла (страница 13)
{
leftVar = new QueryVariable(varName, leftClassName);
variables.Add(leftVar);
}
#endregion
#region Правая переменная отношения
varName = RelationParts.Last();
k = variables.FindIndex(v => v.Name == varName);
if (k >= 0)
{
rightVar = variables[k];
rightVar.AddClass(rightClassName);
}
else
{
rightVar = new QueryVariable(varName, rightClassName);
variables.Add(rightVar);
}
#endregion
relVar.AddClassAttribute(leftClassName, leftVar);
relVar.AddClassAttribute(rightClassName, rightVar);
Relation relation = new Relation(leftVar, relVar, rightVar);
RelationVars.Add(relation);
continue;
}
else if(openBracketPosition != -1)
{
int closeBracketPosition = s.IndexOf(')');
if (openBracketPosition > closeBracketPosition)
throw new TranslatorException("Лишняя закрывающяя скобка в выражении " + s);
varName = s.Substring(openBracketPosition + 1, closeBracketPosition - openBracketPosition - 1);
string relType = s.Substring(0, openBracketPosition);
string rest = s.Substring(closeBracketPosition + 1);
if (rest.IndexOf(')') != -1)
throw new TranslatorException("Лишняя закрывающяя скобка в выражении " + s);
int relIndex = scheme.Relations.FindIndex(rel => rel.Name == relType);
if (relIndex == -1)
throw new TranslatorException("Неизвестное отношение \"" +relType + "\"в выражении "+s);
QueryVariable leftVar;
QueryVariable rightVar;
int varIndex = variables.FindIndex(var => var.Name == varName);
if (varIndex >= 0)
{
leftVar = variables[varIndex];
leftVar.AddClass(scheme.Relations[relIndex].Left.Name);
}
else
{
leftVar = new QueryVariable(varName, scheme.Relations[relIndex].Left.Name);
variables.Add(leftVar);
}
string artifName = "__" + artificialVarsCount;
artificialVarsCount++;
rightVar = new QueryVariable(artifName, scheme.Relations[relIndex].Right.Name);
variables.Add(rightVar);
s = artifName + rest;
artifName = "__" + artificialVarsCount;
artificialVarsCount++;
variables.Add(new QueryVariable(artifName, scheme.Relations[relIndex].Name));
variables.Last().AddClassAttribute(leftVar.Class.Name, leftVar);
variables.Last().AddClassAttribute(rightVar.Class.Name, rightVar);
RelationVars.Add(new Relation(leftVar,variables.Last(),rightVar));
}
#endregion
conditionParts.Add(s);
}
for (int i = 0; i < conditionParts.Count; i++)
{
string s = conditionParts[i].Trim();
#region Обработка условия
#region Проверка на присутствие операторов
bool operatorIsIn = false;
string operatorStr = "";
string cumulativeStr = "";
for (int j = 0; j < s.Length; j++)
{
if (j != (s.Length - 1) && s[j] == '<' && s[j + 1] == '=')
{
if (operatorIsIn)
throw new TranslatorException("В выражении " + s + " несколько операторов");
operatorIsIn = true;
operatorStr = "<=";
j += 2;
}
if (j != (s.Length - 1) && s[j] == '>' && s[j + 1] == '=')
{
if (operatorIsIn)
throw new TranslatorException("В выражении " + s + " несколько операторов");
operatorIsIn = true;
operatorStr = ">=";
j += 2;
}
if (j != (s.Length - 1) && s[j] == '<' && s[j + 1] != '=')
{
if (operatorIsIn)
throw new TranslatorException("В выражении " + s + " несколько операторов");
operatorIsIn = true;
operatorStr = "<";
j++;
}
if (j != (s.Length - 1) && s[j] == '>' && s[j + 1] != '=')
{
if (operatorIsIn)
throw new TranslatorException("В выражении " + s + " несколько операторов");
operatorIsIn = true;
operatorStr = ">";
j++;
}
if (j != (s.Length-1) && s[j] == '=')
{
if (operatorIsIn)
throw new TranslatorException("В выражении " + s + " несколько операторов");
operatorIsIn = true;
operatorStr = "=";
j++;
}
cumulativeStr += s[j];
}
if (!operatorIsIn)
throw new TranslatorException("В выражении " + s + " отсутствует оператор");
#endregion
string[] condparts = s.Split(operatorStr.ToArray(),StringSplitOptions.RemoveEmptyEntries);
#region Обработка короткой левой части
// if (condparts.Length > 2) Не может такого быть - ошибка, когда больше двух обрабатывается раньше
// throw new TranslatorException("В условии много операторов");
string[] leftParts = condparts[0].Split('.');
if (leftParts.Length > 2) // Из одного условия делается несколько с использованием новых переменных
{
varName = leftParts[0].Trim();
string artVarName = "__" + artificialVarsCount;
conditionParts.RemoveAt(i--);
string DividedConj;
for (int j = 1; j < leftParts.Length - 1; j++)
{
artificialVarsCount++;
DividedConj = varName + "." + leftParts[j] + "=" + artVarName;
conditionParts.Insert(i + j , DividedConj);
varName = artVarName;
artVarName = "__" + artificialVarsCount;
}
DividedConj = varName + "." + leftParts.Last() + operatorStr + condparts[1];
conditionParts.Insert(i + leftParts.Length - 1, DividedConj);
continue;
}
#endregion
#region Обработка короткой правой части
string[] rightParts = condparts[1].Split('.');
if (rightParts.Length >= 2) // Из одного условия делается несколько с использованием новых переменных
{
varName = rightParts[0].Trim();
if (scheme.Classes.FindIndex(cl => cl.Name == varName) >= 0 ||
scheme.Relations.FindIndex(rel => rel.Name == varName) >= 0)
{
string artifName = "__" + artificialVarsCount;
artificialVarsCount++;
variables.Add(new QueryVariable(artifName, varName));
varName = artifName;
}
if (rightParts.Length > 2)
{
string artVarName = "__" + artificialVarsCount;
conditionParts.RemoveAt(i--);
string DividedConj;
for (int j = 1; j < rightParts.Length - 1; j++)
{
artificialVarsCount++;
DividedConj = varName + "." + rightParts[j] + "=" + artVarName;
conditionParts.Insert(i + j, DividedConj);
varName = artVarName;
artVarName = "__" + artificialVarsCount;
}
DividedConj = leftParts[0];
for (int j = 1; j < leftParts.Length; j++)
{
DividedConj += "." + leftParts[j];
}
DividedConj += operatorStr + varName + "." + rightParts.Last();
conditionParts.Insert(i + rightParts.Length - 1, DividedConj);
continue;
}
}
#endregion
varName = leftParts[0].Trim();
attrName = leftParts[1].Trim();
// Если не содержит точку, значит - известное значение
if (rightParts.Length <= 2)
{
k = variables.FindIndex(v => v.Name == varName);
if (k == -1)
throw new TranslatorException("Переменная " + varName + " неизвестного типа");
if (variables[k].Class.isSimpleAttribute(attrName))
{
if (rightParts.Length == 2)
{
QueryVariable rightvar;
int l = variables.FindIndex(v => v.Name == rightParts[0]);
rightvar = variables.ElementAt(l);
variables[k].AddComplexAttribute(attrName);
rightvar.AddComplexAttribute(rightParts[1]);
AttrPairs.Add(new AttrPair(variables[k],attrName,operatorStr,rightvar,rightParts[1]));
}
else
{
string value = condparts[1].Trim();
variables[k].AddSimpleAttribute(attrName, operatorStr, value);
}
}
else if (variables[k].Class.isClassAttribute(attrName))
{
if (operatorStr != "=")
throw new TranslatorException("Ошибка записи в выражении" + s + ". В аттрибутах, где используются суррогаты можно использовать только оператор \"=\"");
string newvarName = condparts[1].Trim();
QueryVariable newvar;
int l = variables.FindIndex(v => v.Name == newvarName);
if (l >= 0)
{
newvar = variables.ElementAt(l);
newvar.AddClassOnAttribute(variables[k], attrName);
}
else
{
newvar = new QueryVariable(variables[k], newvarName, attrName);
variables.Add(newvar);
}
variables[k].AddClassAttribute(attrName, newvar);
}
else
throw new TranslatorException("Переменная " + variables[k].Name + " относится к классу " + variables[k].Class.Name +
", но в этом классе не содержится аттрибут \"" + attrName + "\"");
continue;
}
#endregion
}
}
void checkVariablesClass()
{
foreach (QueryVariable qv in variables)
{
if (qv.Class == null)
throw new TranslatorException("Переменная " + qv.Name + " неизвестного типа");
foreach(string classAttr in qv.ClassAttributes)
{
if (!qv.Class.isClassAttribute(classAttr))
throw new TranslatorException("Переменная " + qv.Name + " относится к классу " + qv.Class +
", но в этом классе не содержится аттрибут \"" + classAttr + "\"");
}
foreach(string classAttr in qv.ClassAttributes)
{
if (!qv.Class.isClassAttribute(classAttr))
throw new TranslatorException("Переменная " + qv.Name + " относится к классу " + qv.Class +
", но в этом классе не содержится аттрибут \"" + classAttr + "\"");
}
}
}
void removeUselessVariables()
{
List<QueryVariable> necessaryVars = new List<QueryVariable>(goalVariables);
List<QueryVariable> uselessVars = (new List<QueryVariable>(variables)).Except(goalVariables).ToList();
for (int i = 0; i < necessaryVars.Count; i++)
{
if (uselessVars.Count == 0)
break;
int j = AttrPairs.FindIndex(ap => necessaryVars[i].Name == ap.qv1.Name);
if (j != -1)
{
if (!necessaryVars.Contains(AttrPairs[j].qv2))
necessaryVars.Add(AttrPairs[j].qv2);
uselessVars.Remove(AttrPairs[j].qv2);
}
j = AttrPairs.FindIndex(ap => necessaryVars[i].Name == ap.qv2.Name);
if (j != -1)
{
if (!necessaryVars.Contains(AttrPairs[j].qv1))
necessaryVars.Add(AttrPairs[j].qv1);
uselessVars.Remove(AttrPairs[j].qv1);
}
for (j = 0; j < uselessVars.Count; j++)
{
if (necessaryVars[i].ClassVariables.Contains(uselessVars[j]) ||
uselessVars[j].ClassVariables.Contains(necessaryVars[i]))
{
necessaryVars.Add(uselessVars[j]);
uselessVars.Remove(uselessVars[j]);
j--;
}
}
}
variables = new List<QueryVariable>(necessaryVars);
}
string EscapeKeyword(string word)
{
string wordInUpper = word.ToUpper();
if (wordInUpper == "GROUP")
return "[" + word +"]";
return word;
}
string CreateSQLSubQuery(QueryVariable qv)
{
string subquery = "SELECT id";
List<string> requiredAttributes;
if (goalVariables.Contains(qv))
{
requiredAttributes = qv.ClassAttributes.Union(qv.NeededAttributes).ToList();
}
else
requiredAttributes = qv.ClassAttributes;
requiredAttributes = requiredAttributes.Union(qv.ComplexAttributes).Distinct().ToList();
for (int i = 0; i < requiredAttributes.Count; i++)
{
if (requiredAttributes[i] != "id")
subquery += ", " + EscapeKeyword(requiredAttributes[i]);
}
subquery += " FROM " + EscapeKeyword(qv.Class.Name);
if (qv.SimpleAttributes.Count != 0)
{
subquery += " WHERE ";
subquery += qv.SimpleAttributes[0] + qv.SimpleAttributeOperators[0] + qv.SimpleAttributeValues[0];














