Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Разработка языка запросов в бинарной модели знаний и транслятора этого языка в язык SQL (бакалаврская работа).doc
Скачиваний:
13
Добавлен:
28.06.2014
Размер:
1.31 Mб
Скачать

Файл Translator.Cs

using System;

using System.Data;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace Запросы

{

class TranslatorException : Exception

{

public TranslatorException() { }

public TranslatorException(string message) : base(message) { }

public TranslatorException(string message, Exception inner) : base(message, inner) { }

}

/// <summary>

/// Транслирует язык запросов на язык SQL

/// </summary>

class Translator

{

/// <summary>

/// Класс, описывающий переменную, ее тип и известные значения.

/// </summary>

class QueryVariable

{

static public OnthologyScheme scheme;

string name;

OnthologyClass oclass;

List<string> neededAttributes;

List<string> complexAttributes;

List<string> simpleAttributes;

List<string> simpleAttributeOperators;

List<string> simpleAttributeValues;

List<string> classAttributes;

List<QueryVariable> classVariables;

public QueryVariable(string _name, string className)

: this(_name)

{

AddClass(className);

}

public QueryVariable(QueryVariable parentVar, string _name, string className)

: this(_name)

{

AddClassOnAttribute(parentVar, className);

}

public QueryVariable(string _name)

{

name = _name;

oclass = null;

simpleAttributes = new List<string>();

neededAttributes = new List<string>();

simpleAttributeValues = new List<string>();

simpleAttributeOperators = new List<string>();

complexAttributes = new List<string>();

classAttributes = new List<string>();

classVariables = new List<QueryVariable>();

}

public void AddClass(string className)

{

OnthologyClass oc = scheme.Classes.Find(c => c.Name == className);

if (oc == null)

oc = scheme.Relations.Find(c => c.Name == className);

if (oc == null)

throw new TranslatorException("Переменная " + Name + " имеет неопределенный в схеме класс: " + className);

if (oclass != null && oclass != oc)

throw new TranslatorException("Неоднозначный тип у переменной " + Name + ". Возможные значения типов:" + className + "," + oclass.Name);

oclass = oc;

}

public void AddClassOnAttribute(QueryVariable parentVar, string attributeClassName)

{

if (parentVar.Class is OnthologyRelation)

{

OnthologyRelation ontRel = (OnthologyRelation)parentVar.Class;

if (ontRel.Left.Name.ToUpper() == attributeClassName.ToUpper())

oclass = ontRel.Left;

if (ontRel.Right.Name.ToUpper() == attributeClassName.ToUpper())

oclass = ontRel.Right;

}

else

{

oclass = parentVar.Class.ClassAttributes.Find(c => c.Name.ToUpper() == attributeClassName.ToUpper()).Type;

}

}

public void AddNeededAttribute(string attr)

{

neededAttributes.Add(attr);

}

public void AddComplexAttribute(string attr)

{

complexAttributes.Add(attr);

}

public void AddSimpleAttribute(string attr, string attrOperator, string value)

{

simpleAttributes.Add(attr);

simpleAttributeOperators.Add(attrOperator);

simpleAttributeValues.Add(value);

}

public void AddClassAttribute(string attr, QueryVariable qv)

{

classAttributes.Add(attr);

classVariables.Add(qv);

}

public void DefineClass()

{

if (oclass == null)

for (int i = 0; i < scheme.Classes.Count; i++)

{

OnthologyClass oc = scheme.Classes[i];

if (attrIsInColumns(oc, neededAttributes) && attrIsInColumns(oc, simpleAttributes))

{

oclass = oc;

return;

}

}

}

bool attrIsInColumns(OnthologyClass Class, List<string> QueryAttributes)

{

bool allAttrsInTable = true;

foreach (string queryAttrName in QueryAttributes)

{

bool attrIsInColumns = false;

foreach (OnthologyAttribute<string> classAttr in Class.SimpleAttributes)

{

if (queryAttrName == classAttr.Name)

{

attrIsInColumns = true;

break;

}

}

if (!attrIsInColumns)

{

allAttrsInTable = false;

break;

}

}

return allAttrsInTable;

}

public string Name

{

get

{

return name;

}

}

public OnthologyClass Class

{

get

{

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

{

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];

for (int i = 1; i < qv.SimpleAttributes.Count; i++)

{

subquery += " AND " + qv.SimpleAttributes[i] + qv.SimpleAttributeOperators[i] + qv.SimpleAttributeValues[i];

}

}

return subquery;

}

#region SQLQuery VERSION ACTIVE

string CreateSQLQuery(string query)

{

if (goalVariables.Count == 0)

throw new TranslatorException("Не задана целевая переменая");

SQLquery = "SELECT DISTINCT ";

bool firstVariableProceeded = false;

for (int i = 0; i < goalVariables.Count; i++)

{

QueryVariable goalVar = goalVariables[i];

if (goalVar.Class == null)

throw new TranslatorException("Переменная " + goalVar.Name + " неизвестного типа");

for (int j = 0; j < goalVar.NeededAttributes.Count; j++)

{

if (!firstVariableProceeded)

firstVariableProceeded = true;

else

SQLquery += ", ";

string neededAttrSQL = EscapeKeyword(goalVar.Name) + "." + EscapeKeyword(goalVar.NeededAttributes[j]);

if (aggregateFunction != null)

neededAttrSQL = aggregateFunction + "( " + neededAttrSQL + ")";

SQLquery += neededAttrSQL;

}

}

SQLquery += Environment.NewLine;

SQLquery += "FROM " + "(" + CreateSQLSubQuery(variables[0]) + ") AS " + variables[0].Name;

for (int i = 1; i < variables.Count; i++)

SQLquery += Environment.NewLine + "CROSS JOIN " + "(" + CreateSQLSubQuery(variables[i]) + ") AS " + variables[i].Name;

if (variables.Count > 1)

{

SQLquery += Environment.NewLine + "WHERE ";

firstVariableProceeded = false;

for (int i = 0; i < variables.Count; i++)

{

for (int j = 0; j < variables[i].ClassAttributes.Count; j++)

{

if (!firstVariableProceeded)

firstVariableProceeded = true;

else

SQLquery += " AND ";

SQLquery += variables[i].Name + "." + EscapeKeyword(variables[i].ClassAttributes[j]) +

" = " + EscapeKeyword(variables[i].ClassVariables[j].Name) + ".id";

}

}

for (int i = 0; i < AttrPairs.Count; i++)

{

SQLquery += " AND "+ AttrPairs[i].qv1.Name + "." + AttrPairs[i].attr1 + AttrPairs[i].attrOperator + AttrPairs[i].qv2.Name + "." + AttrPairs[i].attr2;

}

}

return SQLquery;

}

#endregion

#region Свойства

public string Query

{

get

{

return query;

}

}

public string SQLQuery

{

get

{

return SQLquery;

}

}

public string Select

{

get

{

return select;

}

}

public string Condition

{

get

{

return condition;

}

}

#endregion

}

}

Соседние файлы в предмете Государственный экзамен