/// <summary> /// Processes the attributes. /// </summary> /// <param name="entityMap">Entity mapping whitch contains the attribute</param> /// <param name="name">Name of the attribute</param> /// <param name="loadAttributes"></param> /// <param name="checkAlias">Indicate if returned column must have an computed alias name or not</param> /// <returns>Return a <see cref="Column"/></returns> public ISQLExpression ProcessAttributes(EntityMapping entityMap, string name, bool loadAttributes, bool checkAlias) { if (name == "Id") { Table currentTable = (Table)tableContext.Peek(); return new Column(entityMap.Ids[0], currentTable.TableAlias, entityMap.GetIdField(entityMap.Ids[0])); } else { // Exception management : attribute mapping AttributeMapping attributeMapping = entityMap.Attributes[name]; //Attempt to get the attribute in the children types if (attributeMapping == null) foreach (Evaluant.Uss.Models.Entity e in _Model.GetTree(entityMap.Type)) { EntityMapping em = _Mapping.Entities[e.Type]; if ((attributeMapping = em.Attributes[name]) != null) break; } //Attempt to get the attribute in the parent types if (attributeMapping == null) { Evaluant.Uss.Models.Entity cur = _Model.GetEntity(entityMap.Type); while (_Model.GetParent(cur) != null) { cur = _Model.GetParent(cur); EntityMapping current = _Mapping.Entities[cur.Type]; if (current.Attributes[name] != null) attributeMapping = current.Attributes[name]; } } if (attributeMapping == null) throw new UniversalStorageException(String.Format("The attribute '{0}' of the entity '{1}' is not defined in your mapping file", name, entityMap.Type)); // If the attribute is contained in entity's table : the current query doesn't change if (attributeMapping.Table == entityMap.Table) { Table currentTable = (Table)tableContext.Peek(); Column c = new Column(attributeMapping, currentTable.TableAlias, attributeMapping.Field); //if (entityMap.Ids[attributeMapping.Field] != null) // c.ColumnName = entityMap.GetIdField(entityMap.Ids[attributeMapping.Field]); if (checkAlias) { string attributeFullName = _Model.GetFullAttributeName(attributeMapping.Name, attributeMapping.ParentEntity.Type); //if (entityMap.Ids[attributeMapping.Field] != null) // attributeFullName = entityMap.GetIdFieldAs(entityMap.Ids[attributeMapping.Field]); //c.ColumnName = (_AliasColumnMapping.Contains(attributeFullName)) ? _AliasColumnMapping[attributeFullName].ToString() : ""; if (_AliasColumnMapping.Contains(attributeFullName)) c.ColumnName = _AliasColumnMapping[attributeFullName].ToString(); } return c; } // Else : create a new select query else { // Get the current context Table currentTable = (Table)tableContext.Pop(); SelectStatement mainQuery = (SelectStatement)queryContext.Pop(); // Create a new query SelectStatement currentQuery = new SelectStatement(attributeMapping); Table attributeTable = new TableSource(attributeMapping, attributeMapping.Table, CreateUniqueAttributeAlias()); string atrbId = attributeMapping.Table == null || attributeMapping.Table == entityMap.Table ? entityMap.GetIdField(entityMap.Ids[0]) : attributeMapping.ParentField; if (loadAttributes) { return this.ProcessAttributesWithLoadAttribute(mainQuery, currentQuery, currentTable, entityMap, attributeTable, attributeMapping, atrbId); } else { if (_IsFirstAttribute) { _IsFirstAttribute = false; // if current table is a JoinedTable : // from clause = mainQuery INNER JOIN attributeTable if (currentTable.GetType() == typeof(JoinedTable)) { JoinedTable lastJoinTable = new JoinedTable(mainQuery, loadAttributes ? TypeJoinedTable.LeftOuter : TypeJoinedTable.Inner, attributeTable); lastJoinTable.TableAlias = mainQuery.TableAlias; BinaryLogicExpression onCondition = new BinaryLogicExpression( new Column(entityMap.Ids[0], mainQuery.TableAlias, entityMap.GetIdField(entityMap.Ids[0])), BinaryLogicOperator.Equals, new Column(attributeMapping, attributeTable.TableAlias, atrbId)); if (mainQuery.WhereClause.SearchCondition.Count != 0) { foreach (ILogicExpression expression in mainQuery.WhereClause.SearchCondition) { onCondition = new BinaryLogicExpression(onCondition, BinaryLogicOperator.And, expression); } } lastJoinTable.SearchConditions.Add(new BinaryLogicExpression( new Column(entityMap.Ids[0], mainQuery.TableAlias, entityMap.GetIdField(entityMap.Ids[0])), BinaryLogicOperator.Equals, new Column(entityMap.Ids[0], attributeTable.TableAlias, atrbId))); currentQuery.TableAlias = mainQuery.TableAlias; currentQuery.FromClause.Add(lastJoinTable); currentQuery.WhereClause.SearchCondition.Add(new BinaryLogicExpression( new Column(attributeMapping, attributeTable.TableAlias, attributeMapping.Discriminator), BinaryLogicOperator.Equals, new Constant(name, DbType.AnsiString))); tableContext.Push(lastJoinTable); queryContext.Push(currentQuery); return new Column(attributeMapping, attributeTable.TableAlias, attributeMapping.Field); } // else // from clause = currentTable INNER JOIN attributeTable else { JoinedTable joinTable = new JoinedTable(currentTable, loadAttributes ? TypeJoinedTable.LeftOuter : TypeJoinedTable.Inner, attributeTable); joinTable.SearchConditions.Add(new BinaryLogicExpression( new Column(entityMap.Ids[0], currentTable.TableAlias, entityMap.GetIdField(entityMap.Ids[0])), BinaryLogicOperator.Equals, new Column(attributeMapping, attributeTable.TableAlias, atrbId))); currentQuery.TableAlias = CreateUniqueTableAlias(); currentQuery.FromClause.Add(joinTable); currentQuery.WhereClause.SearchCondition = mainQuery.WhereClause.SearchCondition; tableContext.Push(joinTable); } } else { Table rightTable = ((JoinedTable)currentTable).RigthTable; JoinedTable joinTable = new JoinedTable(attributeTable, TypeJoinedTable.Inner, rightTable); joinTable.SearchConditions.Add(new BinaryLogicExpression( new Column(attributeMapping, rightTable.TableAlias, atrbId), BinaryLogicOperator.Equals, new Column(attributeMapping, attributeTable.TableAlias, atrbId))); ((JoinedTable)currentTable).RigthTable = joinTable; currentQuery.SelectList.Add(new Column(entityMap.Ids[0], currentTable.TableAlias, entityMap.GetIdField(entityMap.Ids[0]))); currentQuery.TableAlias = currentTable.TableAlias; currentQuery.FromClause.Add(currentTable); tableContext.Push(currentTable); } queryContext.Push(currentQuery); return new Column(attributeMapping, attributeTable.TableAlias, attributeMapping.Field); } } } }
/// <summary> /// /// </summary> /// <param name="firstIsType"></param> /// <param name="isInConstraint"></param> /// <param name="lastIsAttribute"></param> /// <param name="overrideId">True, if the Path is into a constraint and queried an attribute through Reference /// (Person[Brother.MyKind.Name = 'nice'])</param> public void ConvertToSQL(Path path, bool firstIsType, bool isInConstraint, bool lastIsAttribute, bool overrideId) { int index = 0; // Process the first entity if (firstIsType) { Identifier ident = path.Identifiers[index++]; // Exception management : entity mapping EntityMapping entityMapping = _Mapping.Entities[ident.Value, true]; // Save entity mapping current context entityMappingContext.Push(entityMapping); entityModelContext.Push(_Model.GetEntity(ident.Value, true)); ProcessEntity(ident, false); } // Restore the first entity context EntityMapping firstMapping = (EntityMapping)entityMappingContext.Peek(); Table firstTable = (Table)tableContext.Peek(); // Process references int lastIndex = lastIsAttribute ? path.Identifiers.Count - 1 : path.Identifiers.Count; bool isFirstReference = true; ArrayList collEpression = new ArrayList(); int stackCount = entityMappingContext.Count; Evaluant.Uss.Models.Entity previousEntityModel = (Evaluant.Uss.Models.Entity)entityModelContext.Peek(); for (; index < lastIndex; index++) { Identifier ident = path.Identifiers[index]; UnionStatement childrenSubExp = new UnionStatement(); //childrenSubExp.TableAlias = ident.Value; Evaluant.Uss.Models.Reference reference = _Model.GetReference(previousEntityModel.Type, ident.Value, true); // ident.Value isn't a reference but an attribute if (_Model.GetReference(previousEntityModel.Type, ident.Value) == null && _Model.GetAttribute(previousEntityModel.Type, ident.Value) != null) { EntityMapping tmpMap = _Mapping.Entities[previousEntityModel.Type]; entityMappingContext.Push(tmpMap); entityModelContext.Push(_Model.GetEntity(previousEntityModel.Type)); continue; } Evaluant.Uss.Models.Entity currentModel = previousEntityModel; //Model.GetEntity(previousEntityModel.Type); while (_Model.GetParent(currentModel) != null && reference == null) { currentModel = Model.GetParent(currentModel); // ident.Value isn't a reference but an attribute if (_Model.GetReference(currentModel.Type, ident.Value) == null && _Model.GetAttribute(currentModel.Type, ident.Value) != null) continue; reference = _Model.GetReference(currentModel.Type, ident.Value); if (reference != null) break; } // Restore parent context EntityMapping parentMapping = index == 0 && isInConstraint ? (EntityMapping)entityMappingContext.Peek() : (EntityMapping)entityMappingContext.Pop(); Evaluant.Uss.Models.Entity parentModel = index == 0 && isInConstraint ? (Evaluant.Uss.Models.Entity)entityModelContext.Peek() : (Evaluant.Uss.Models.Entity)entityModelContext.Pop(); string cType = reference.ChildType; previousEntityModel = _Model.GetEntity(cType, true); Table parentTable = (Table)tableContext.Pop(); SelectStatement parentQuery = (SelectStatement)queryContext.Pop(); // Get tree for reference.ChildType IList childrenSubTypes = _Model.GetTree(cType); // Get all fullname attributes StringCollection attributes = new StringCollection(); attributes.AddRange(_Model.GetFullAttributesNames(cType)); Hashtable subQueries = new Hashtable(); foreach (Evaluant.Uss.Models.Entity child in childrenSubTypes) { if (_Mapping.Entities[child.Type] == null) continue; string refName = ident.Value; ReferenceMapping referenceMapping = parentMapping.References[refName]; Evaluant.Uss.Models.Entity current = Model.GetEntity(parentMapping.Type); if (referenceMapping == null) { while (_Model.GetParent(current) != null) { current = Model.GetParent(current); referenceMapping = _Mapping.Entities[current.Type].References[refName]; if (referenceMapping != null) break; } } if (referenceMapping == null) throw new MappingNotFoundException(String.Format("Reference [{0}] not found in Type [{1}]", ident.Value, parentMapping.Type)); RuleMappingCollection ruleMapping = referenceMapping.Rules; // Save child mapping context EntityMapping childMapping = _Mapping.Entities[child.Type]; entityMappingContext.Push(childMapping); entityModelContext.Push(_Model.GetEntity(child.Type)); // Process child mapping reference ProcessEntity(ident, true); // Restore child context Table childTable = (Table)tableContext.Pop(); SelectStatement childQuery = (SelectStatement)queryContext.Pop(); childQuery.TableAlias = childTable.TableAlias; childQuery.SelectList = new ExpressionCollection(); // Begin to the first INNER JOIN Table righFirstTableJoinTable = null; // la référence précedente a une contrainte avec Attribute Table de type INNER JOIN if (isFirstReference && parentTable.GetType() == typeof(JoinedTable)) righFirstTableJoinTable = parentQuery; // la référence précedente suit une autre référence de type INNER JOIN else if (!isFirstReference && parentTable.GetType() == typeof(JoinedTable)) { righFirstTableJoinTable = parentTable; foreach (ILogicExpression exp in parentQuery.WhereClause.SearchCondition) { childQuery.WhereClause.SearchCondition.Add(exp); } } // autre cas else if (parentTable.GetType() == typeof(TableSource)) { righFirstTableJoinTable = parentTable; // Ajoute les clauses Wheres de la table courante if (!isInConstraint) foreach (ILogicExpression exp in parentQuery.WhereClause.SearchCondition) { childQuery.WhereClause.SearchCondition.Add(exp); } } else { righFirstTableJoinTable = parentTable; if (righFirstTableJoinTable.TableAlias == null || righFirstTableJoinTable.TableAlias == string.Empty) righFirstTableJoinTable.TableAlias = refName; } Table leftFirstJoinTable = ruleMapping.Count != 1 ? new TableSource(ruleMapping[0], ruleMapping[0].ChildTable, "rule" + index) : childTable; string parentFieldTable = righFirstTableJoinTable.TableAlias; for (int indexId = 0; indexId < referenceMapping.EntityParent.Ids.Count; indexId++) { PrimaryKeyMapping pmk = referenceMapping.EntityParent.Ids[indexId]; string idfield = string.Empty; if (righFirstTableJoinTable.GetType() == typeof(TableSource)) idfield = referenceMapping.EntityParent.GetIdField(pmk); else idfield = referenceMapping.EntityParent.GetIdFieldAs(pmk); string alias = GetParentIdAlias(referenceMapping.EntityParent, pmk.Field); childQuery.SelectList.Add(new Column(ruleMapping[0], parentFieldTable, idfield, alias)); } // Multiple Key foreach (PrimaryKeyMapping pkm in childMapping.Ids) childQuery.SelectList.Add(new Column(ruleMapping[ruleMapping.Count - 1], childQuery.TableAlias, childMapping.GetIdField(pkm), childMapping.GetIdFieldAs(pkm))); // adds all foreign keys contained in the current table that will be used by the next reference if (index + 1 < lastIndex) { Identifier nextIdent = path.Identifiers[index + 1]; Models.Entity type = child; while (_Mapping.Entities[type.Type].References[nextIdent.Value] == null) type = Model.GetEntity(type.Inherit, true); if (_Mapping.Entities[type.Type].References[nextIdent.Value] == null) break; RuleMappingCollection rules = _Mapping.Entities[type.Type].References[nextIdent.Value].Rules; if (rules.Count == 1 && rules[0].ParentField != referenceMapping.EntityParent.IdFields && rules[0].ParentField != childMapping.IdFields) { foreach (string parentField in rules[0].ParentField.Split(SqlMapperProvider.IDSEP)) childQuery.SelectList.Add(new Column(rules[0], childQuery.TableAlias, parentField, parentField)); } } // specify relation role name if (!string.IsNullOrEmpty(referenceMapping.DiscriminatorField)) { childQuery.WhereClause.SearchCondition.Add( new BinaryLogicExpression( new Column(referenceMapping, leftFirstJoinTable.TableAlias, referenceMapping.DiscriminatorField), BinaryLogicOperator.Equals, new Constant(referenceMapping.DiscriminatorValue, DbType.AnsiString) )); } // inner join on index table FK_Parent JoinedTable firstJoinTable = new JoinedTable(leftFirstJoinTable, TypeJoinedTable.Inner, righFirstTableJoinTable); firstJoinTable.TableAlias = leftFirstJoinTable.TableAlias; for (int indexId = 0; indexId < ruleMapping[0].ParentFields.Length; indexId++) { string childField = ruleMapping[0].ChildFields[indexId]; string parentField = ruleMapping[0].ParentFields[indexId]; string idField = parentMapping.Ids.Count > indexId ? parentMapping.Ids[indexId].Field : string.Empty; string parentid = ruleMapping[0].GetParentFieldAs(); if (righFirstTableJoinTable.GetType() == typeof(TableSource) || (ruleMapping.Count == 1 && parentField != idField)) parentid = parentField; firstJoinTable.SearchConditions.Add(new BinaryLogicExpression( new Column(ruleMapping[0], righFirstTableJoinTable.TableAlias, parentid), BinaryLogicOperator.Equals, new Column(ruleMapping[0], leftFirstJoinTable.TableAlias, childField))); } if (!string.IsNullOrEmpty(childMapping.DiscriminatorField)) { BinaryLogicExpression discriminator = new BinaryLogicExpression( new Column(childMapping, childQuery.TableAlias, childMapping.DiscriminatorField), BinaryLogicOperator.Equals, new Constant(childMapping.DiscriminatorValue, DbType.AnsiStringFixedLength) ); childQuery.WhereClause.SearchCondition.Add(discriminator); } if (ruleMapping.Count == 1) childQuery.FromClause.Add(firstJoinTable); // Fin Construction du premier INNER JOIN if (isInConstraint && ruleMapping.Count == 1 && index == 0) { // Restore the first entity context Table mainTable = (Table)tableContext.Peek(); if (ruleMapping[0].ParentFields.Length > 1) { MultipledKey parentKey = new MultipledKey(ruleMapping[0]); MultipledKey childKey = new MultipledKey(ruleMapping[0]); foreach (string key in ruleMapping[0].ParentFields) { parentKey.Collection.Add(new Column(ruleMapping[0], firstTable.TableAlias, key)); // parent table/column link childKey.Collection.Add(new Column(ruleMapping[0], mainTable.TableAlias, key)); // child table/column link } linkTableContext.Push(parentKey); // parent table/column link linkTableContext.Push(childKey); // child table/column link } else { linkTableContext.Push(new Column(ruleMapping[0], firstTable.TableAlias, ruleMapping[0].ParentField)); // parent table/column link linkTableContext.Push(new Column(ruleMapping[0], mainTable.TableAlias, ruleMapping[0].ParentField)); // child table/column link } } tableContext.Push(firstJoinTable); for (int i = 1; i < ruleMapping.Count; i++) { firstJoinTable = (JoinedTable)tableContext.Pop(); JoinedTable lastJoinTable = null; // la référence courante possède une contrainte qui est de type INNER JOIN if (ident.Constraint != null && childTable.GetType() == typeof(JoinedTable)) { SelectStatement query = new SelectStatement(referenceMapping); query.TableAlias = childTable.TableAlias; lastJoinTable = new JoinedTable(childQuery, TypeJoinedTable.Inner, firstJoinTable); lastJoinTable.TableAlias = childQuery.TableAlias; lastJoinTable.SearchConditions.Add(new BinaryLogicExpression( new Column(ruleMapping[i], childQuery.TableAlias, ruleMapping[i].ChildField), BinaryLogicOperator.Equals, new Column(ruleMapping[i], leftFirstJoinTable.TableAlias, ruleMapping[i].ParentField))); query.SelectList.Add(new Column(childMapping.Ids[0], childQuery.TableAlias, childMapping.GetIdField(childMapping.Ids[0]))); childQuery = query; tableContext.Push(lastJoinTable); } else { Table leftTable = i == ruleMapping.Count - 1 ? childTable : new TableSource(ruleMapping[i], ruleMapping[i].ChildTable, String.Concat("rule", index + i)); Table rightTable = firstJoinTable; lastJoinTable = new JoinedTable(leftTable, TypeJoinedTable.Inner, rightTable); lastJoinTable.TableAlias = leftTable.TableAlias; // inner join on index table FK_Child lastJoinTable.SearchConditions.Add(new BinaryLogicExpression( new Column(ruleMapping[i], leftTable.TableAlias, ruleMapping[i].ChildField), BinaryLogicOperator.Equals, new Column(ruleMapping[i], rightTable.TableAlias, ruleMapping[i].ParentField))); tableContext.Push(lastJoinTable); } // it's a last rule if (i == ruleMapping.Count - 1) { lastJoinTable = (JoinedTable)tableContext.Pop(); if (isInConstraint && index == lastIndex - 1) { // Restore the first entity context EntityMapping mainMapping = (EntityMapping)entityMappingContext.Peek(); Table mainTable = (Table)tableContext.Peek(); string parentField = firstMapping.GetIdField(firstMapping.Ids[0]); if (path.Identifiers.Count > 1 && (!lastIsAttribute || overrideId)) parentField = "ParentId"; linkTableContext.Push(new Column(firstMapping.Ids[0], parentTable.TableAlias, parentField)); // parent table/column link linkTableContext.Push(new Column(firstMapping.Ids[0], mainTable.TableAlias, firstMapping.GetIdField(firstMapping.Ids[0]))); // child table/column link } if (referenceMapping.DiscriminatorField != null && referenceMapping.Name != "*") { BinaryLogicExpression condition = new BinaryLogicExpression( new Column(referenceMapping, leftFirstJoinTable.TableAlias, referenceMapping.DiscriminatorField), BinaryLogicOperator.Equals, new Constant(ident.Value, DbType.AnsiString)); collEpression.Add(condition); } childQuery.FromClause.Add(lastJoinTable); tableContext.Push(lastJoinTable); } } childQuery.SelectList.Insert(0, new Constant(child.Type, DbType.AnsiString, TYPE_ALIAS)); int attributeTableIndex = 0; foreach (string attName in attributes) { string attNameAlias = attName.Substring(attName.LastIndexOf(DOT) + 1); string shortAttName = attNameAlias; AttributeMapping am = childMapping.Attributes[shortAttName]; // if duplicated attribute name, add an incremented index at the end (if not already done) if (!_IsAliasColumnComputed) { foreach (string colName in _AliasColumnMapping.Values) { if (colName == shortAttName) { if (!_AliasColumnMapping.Contains(attName)) { attNameAlias += ++_AliasColumnIndexNumber; _AliasColumnMapping.Add(attName, attNameAlias); } else attNameAlias = _AliasColumnMapping[attName].ToString(); break; } } } else { // get the previous computed alias attNameAlias = _AliasColumnMapping[attName].ToString(); } if (am != null) { if (am.Table == childMapping.Table) { childQuery.SelectList.Add(new Column(am, childQuery.TableAlias, am.Field, attNameAlias)); } if (am.Table != childMapping.Table && childMapping.Ids[0].Generator.Name == GeneratorMapping.GeneratorType.inherited) { // Add the Left Join for parent attribute table Table left = childQuery.FromClause[0]; Table right = new TableSource(am.ParentEntity.Ids[0], am.Table, string.Concat("a", attributeTableIndex++)); JoinedTable jt = new JoinedTable(left, TypeJoinedTable.LeftOuter, right); jt.SearchConditions.Add(new BinaryLogicExpression( new Column(null, right.TableAlias, am.ParentField), BinaryLogicOperator.Equals, new Column(null, left.TableAlias, childMapping.GetIdField(childMapping.Ids[0])) )); childQuery.FromClause[0] = jt; childQuery.SelectList.Add(new Column(am, right.TableAlias, am.Field, attNameAlias)); // Get the parent table and insert a clause and then we don't return the // records which have a record in a child table string parentType = string.Empty; if (_Model.GetParent(_Model.GetEntity(child.Type)) != null) parentType = _Model.GetParent(_Model.GetEntity(child.Type)).Type; if (parentType == string.Empty) continue; EntityMapping parentEntityMapping = _Mapping.Entities[parentType]; SelectStatement sel = (SelectStatement)subQueries[parentType]; SelectStatement exludeClause = new SelectStatement(null); exludeClause.SelectedAllColumns = true; exludeClause.FromClause.Add(new TableSource(childMapping, childMapping.Table)); exludeClause.WhereClause.SearchCondition.Add(new BinaryLogicExpression( new Column(parentEntityMapping.Ids[0], sel.TableAlias, parentEntityMapping.GetIdField(parentEntityMapping.Ids[0])), BinaryLogicOperator.Equals, new Column(childMapping.Ids[0], childMapping.Table, childMapping.GetIdField(childMapping.Ids[0])))); ExistsPredicate ex = new ExistsPredicate(exludeClause); UnaryLogicExpression ua = new UnaryLogicExpression(UnaryLogicOperator.Not, ex); sel.WhereClause.SearchCondition.Add(ua); } } else { childQuery.SelectList.Add(new Constant(DBNull.Value, DbType.AnsiStringFixedLength, attNameAlias)); } // Store the correspondance between the alias/column name and the attribute name if (!_IsAliasColumnComputed && !_AliasColumnMapping.Contains(attName)) _AliasColumnMapping.Add(attName, attNameAlias); } // entityMappingContext.Pop(); // entityModelContext.Pop(); tableContext.Pop(); //childrenSubExp.SelectExpressions.Add(childQuery); subQueries.Add(child.Type, childQuery); } foreach (SelectStatement sel in subQueries.Values) childrenSubExp.SelectExpressions.Add(sel); childrenSubExp.TableAlias = parentQuery.TableAlias; if (parentQuery.SelectList.Count == 0) { //parentQuery.SelectedAllColumns = true; } //isFirstReference = false; queryContext.Push(childrenSubExp); //entityMappingContext.Push(_Mapping.Entities.GetEntity(cType)); //entityModelContext.Push(_Model.GetEntity(cType)); //if(!isInConstraint) tableContext.Push(childrenSubExp); // queryContext.Push(childQuery); } // if only one attribute if (lastIsAttribute && index == 0) { //FROM [Course] as [e2] //WHERE ([e2].[CourseId] = [e1].[CourseId]) SelectStatement childQuery = (SelectStatement)queryContext.Pop(); firstTable = (Table)tableContext.Pop(); childQuery.FromClause.Add(firstTable); Table mainTable = (Table)tableContext.Peek(); childQuery.WhereClause.SearchCondition.Add( new BinaryLogicExpression(new Column(null, firstTable.TableAlias, firstMapping.GetIdField(firstMapping.Ids[0])), BinaryLogicOperator.Equals, new Column(null, mainTable.TableAlias, firstMapping.GetIdField(firstMapping.Ids[0])))); queryContext.Push(childQuery); tableContext.Push(firstTable); } if (isInConstraint) { int max = entityMappingContext.Count; if (lastIsAttribute) max--; for (int i = max; i > stackCount; i--) { entityMappingContext.Pop(); entityModelContext.Pop(); } } }
public override void Visit(Function function) { bool firstIsType = ((int)_ExprLevel.Peek() == EXPR); _ExprLevel.Push(_ExprLevel.Peek()); ISQLExpression expression = null; EntityMapping entityMap = null; if (!firstIsType) entityMap = (EntityMapping)entityMappingContext.Peek(); SelectStatement subQuery = new SelectStatement(entityMap); int lastIndex = function.Path.Identifiers.Count - 1; if (!firstIsType) { for (int index = 0; index < lastIndex; index++) { string refName = function.Path.Identifiers[index].Value; ReferenceMapping refeMap = entityMap.References[refName]; // If refeMap == null, cannot find the reference in the child // Then try to get it from parent types if (refeMap == null) { Evaluant.Uss.Models.Entity current = Model.GetEntity(entityMap.Type); if (refeMap == null) { while (Model.GetParent(current) != null) { current = Model.GetParent(current); refeMap = _Mapping.Entities[current.Type].References[refName]; if (refeMap != null) { entityMap = refeMap.EntityParent; break; } } } } if (refeMap == null) throw new SqlMapperException(string.Concat("Cannot find the reference", refName, " from the entity ", entityMap.Type)); //entityMap = _Mapping.Entities[refeMap.EntityChild]; } } Table currentTable = null; switch (function.Type) { case FunctionEnum.Average: if (firstIsType) { subQuery = (SelectStatement)TransformToSql(function.Path, new string[0], new string[0], true); ; subQuery.TableAlias = CreateUniqueTableAlias(); if (subQuery is UnionStatement) { SelectStatement select = new SelectStatement(null); select.FromClause.Add(subQuery as Table); subQuery = select; } tableContext.Push(subQuery as Table); _IsFirstAttribute = true; expression = ProcessAttributes((EntityMapping)entityMappingContext.Peek(), function.Path.Identifiers[lastIndex].Value, false, true); subQuery.SelectList = new ExpressionCollection(); subQuery.SelectList.Add(new AggregateFunction(null, AggregateFunctionEnum.Avg, expression)); sqlExpressionContext.Push(subQuery); } else { currentTable = new TableSource(entityMap, ((TableSource)tableContext.Peek()).TableName, CreateUniqueTableAlias()); tableContext.Push(currentTable); queryContext.Push(subQuery); ConvertToSQL(function.Path, false, true, true); expression = ProcessAttributes(entityMap, function.Path.Identifiers[lastIndex].Value, false, true); subQuery = (SelectStatement)queryContext.Peek(); if (subQuery.GetType() == typeof(UnionStatement)) { SelectStatement sel = new SelectStatement(null); subQuery.TableAlias = CreateUniqueTableAlias(); sel.FromClause.Add(subQuery); sel.SelectList = new ExpressionCollection(); sel.SelectList.Add(new AggregateFunction(entityMap, AggregateFunctionEnum.Avg, expression)); sqlExpressionContext.Push(sel); } else { subQuery.SelectList = new ExpressionCollection(); subQuery.SelectList.Add(new AggregateFunction(entityMap, AggregateFunctionEnum.Avg, expression)); sqlExpressionContext.Push(subQuery); } // link tables for inline views ((SelectStatement)sqlExpressionContext.Peek()).WhereClause.SearchCondition.Add(new BinaryLogicExpression(new Column(null, subQuery.TableAlias, "ParentId"), BinaryLogicOperator.Equals, linkTableContext.Pop() as Column)); tableContext.Pop(); queryContext.Pop(); } break; case FunctionEnum.Count: if (firstIsType) { subQuery = (SelectStatement)TransformToSql(function.Path, new string[0], null, false); subQuery.TableAlias = CreateUniqueTableAlias(); if (subQuery is UnionStatement) { SelectStatement select = new SelectStatement(null); select.FromClause.Add(subQuery as Table); subQuery = select; } subQuery.SelectList = new ExpressionCollection(); subQuery.SelectList.Add(new AggregateFunction(null, AggregateFunctionEnum.Count, new Constant("*", DbType.StringFixedLength))); sqlExpressionContext.Push(subQuery); } else { currentTable = new TableSource(entityMap, entityMap.Table, CreateUniqueTableAlias()); tableContext.Push(currentTable); queryContext.Push(subQuery); ConvertToSQL(function.Path, false, true, false); currentTable = (Table)tableContext.Peek(); subQuery = (SelectStatement)queryContext.Peek(); if (subQuery.GetType() == typeof(UnionStatement)) { SelectStatement sel = new SelectStatement(null); subQuery.TableAlias = CreateUniqueTableAlias(); sel.FromClause.Add(subQuery); sel.SelectList = new ExpressionCollection(); sel.SelectList.Add(new AggregateFunction(entityMap, AggregateFunctionEnum.Count, new Constant("*", DbType.StringFixedLength))); sqlExpressionContext.Push(sel); } else { subQuery.SelectList = new ExpressionCollection(); subQuery.SelectList.Add(new AggregateFunction(entityMap, AggregateFunctionEnum.Count, new Constant("*", DbType.StringFixedLength))); sqlExpressionContext.Push(subQuery); } // link tables for inline views ((SelectStatement)sqlExpressionContext.Peek()).WhereClause.SearchCondition.Add(new BinaryLogicExpression(new Column(null, subQuery.TableAlias, "ParentId"), BinaryLogicOperator.Equals, linkTableContext.Pop() as Column)); tableContext.Pop(); queryContext.Pop(); } break; case FunctionEnum.Exists: currentTable = new TableSource(entityMap, entityMap.Table, CreateUniqueTableAlias()); tableContext.Push(currentTable); queryContext.Push(subQuery); ConvertToSQL(function.Path, false, true, false); subQuery = (SelectStatement)queryContext.Peek(); // the exists function just need ids fields // do not list attribute field to avoid problems with data type fields (text, ntext, image for sql server) // Remove none needed selected item, according to the path // no references: keep Type, Id (2 fields) // references: keep Type, IdParent, Id (3 fields) int keepFieldNb = (function.Path.Identifiers.Count == 1) ? 2 : 3; if (subQuery is UnionStatement) { foreach (SelectStatement select in ((UnionStatement)subQuery).SelectExpressions) { for (int i = select.SelectList.Count - 1; i >= keepFieldNb; i--) select.SelectList.RemoveAt(i); // link tables for inline views Column cLeft = linkTableContext.Pop() as Column; Column cRight = linkTableContext.Pop() as Column; if (cLeft is MultipledKey) { for (int index = 0; index < ((MultipledKey)cLeft).Collection.Count; index++) { select.WhereClause.SearchCondition.Add(new BinaryLogicExpression(((MultipledKey)cLeft).Collection[index], BinaryLogicOperator.Equals, ((MultipledKey)cRight).Collection[index])); } } else { select.WhereClause.SearchCondition.Add(new BinaryLogicExpression(cLeft, BinaryLogicOperator.Equals, cRight)); } } } else { for (int i = subQuery.SelectList.Count - 1; i >= keepFieldNb; i--) subQuery.SelectList.RemoveAt(i); // link tables for inline views subQuery.WhereClause.SearchCondition.Add(new BinaryLogicExpression(linkTableContext.Pop() as Column, BinaryLogicOperator.Equals, linkTableContext.Pop() as Column)); } subQuery.SelectedAllColumns = true; expression = new ExistsPredicate(subQuery); sqlExpressionContext.Push(expression); tableContext.Pop(); queryContext.Pop(); break; case FunctionEnum.IsNull: _IsFirstAttribute = true; expression = new IsNullPredicate(ProcessAttributes(entityMap, function.Path.Identifiers[lastIndex].Value, false)); sqlExpressionContext.Push(expression); break; case FunctionEnum.Max: if (firstIsType) { subQuery = (SelectStatement)TransformToSql(function.Path, new string[0], new string[0], true); subQuery.TableAlias = CreateUniqueTableAlias(); if (subQuery is UnionStatement) { SelectStatement select = new SelectStatement(null); select.FromClause.Add(subQuery as Table); subQuery = select; } tableContext.Push(subQuery as Table); _IsFirstAttribute = true; expression = ProcessAttributes((EntityMapping)entityMappingContext.Peek(), function.Path.Identifiers[lastIndex].Value, false, true); subQuery.SelectList = new ExpressionCollection(); subQuery.SelectList.Add(new AggregateFunction(null, AggregateFunctionEnum.Max, expression)); sqlExpressionContext.Push(subQuery); } else { currentTable = new TableSource(entityMap, ((TableSource)tableContext.Peek()).TableName, CreateUniqueTableAlias()); tableContext.Push(currentTable); queryContext.Push(subQuery); entityMappingContext.Push(entityMap); ConvertToSQL(function.Path, false, true, true); EntityMapping lastEM = (EntityMapping)entityMappingContext.Peek(); //entityModelContext.Pop(); entityModelContext.Peek(); expression = ProcessAttributes(lastEM, function.Path.Identifiers[lastIndex].Value, false, true); subQuery = (SelectStatement)queryContext.Peek(); if (subQuery.GetType() == typeof(UnionStatement)) { SelectStatement sel = new SelectStatement(null); subQuery.TableAlias = CreateUniqueTableAlias(); sel.FromClause.Add(subQuery); sel.SelectList = new ExpressionCollection(); sel.SelectList.Add(new AggregateFunction(lastEM, AggregateFunctionEnum.Max, expression)); sqlExpressionContext.Push(sel); } else { subQuery.SelectList = new ExpressionCollection(); subQuery.SelectList.Add(new AggregateFunction(lastEM, AggregateFunctionEnum.Max, expression)); sqlExpressionContext.Push(subQuery); } // link tables for inline views if (linkTableContext.Count > 0) ((SelectStatement)sqlExpressionContext.Peek()).WhereClause.SearchCondition.Add( new BinaryLogicExpression(new Column(null, subQuery.TableAlias, "ParentId"), BinaryLogicOperator.Equals, linkTableContext.Pop() as Column)); tableContext.Pop(); queryContext.Pop(); entityMappingContext.Pop(); } break; case FunctionEnum.Min: if (firstIsType) { subQuery = (SelectStatement)TransformToSql(function.Path, new string[0], new string[0], true); ; subQuery.TableAlias = CreateUniqueTableAlias(); if (subQuery is UnionStatement) { SelectStatement select = new SelectStatement(null); select.FromClause.Add(subQuery as Table); subQuery = select; } tableContext.Push(subQuery as Table); _IsFirstAttribute = true; expression = ProcessAttributes((EntityMapping)entityMappingContext.Peek(), function.Path.Identifiers[lastIndex].Value, false, true); subQuery.SelectList = new ExpressionCollection(); subQuery.SelectList.Add(new AggregateFunction(null, AggregateFunctionEnum.Min, expression)); sqlExpressionContext.Push(subQuery); } else { currentTable = new TableSource(entityMap, ((TableSource)tableContext.Peek()).TableName, CreateUniqueTableAlias()); tableContext.Push(currentTable); queryContext.Push(subQuery); ConvertToSQL(function.Path, false, true, true); expression = ProcessAttributes(entityMap, function.Path.Identifiers[lastIndex].Value, false, true); subQuery = (SelectStatement)queryContext.Peek(); if (subQuery.GetType() == typeof(UnionStatement)) { SelectStatement sel = new SelectStatement(null); subQuery.TableAlias = CreateUniqueTableAlias(); sel.FromClause.Add(subQuery); sel.SelectList = new ExpressionCollection(); sel.SelectList.Add(new AggregateFunction(entityMap, AggregateFunctionEnum.Min, expression)); sqlExpressionContext.Push(sel); } else { subQuery.SelectList = new ExpressionCollection(); subQuery.SelectList.Add(new AggregateFunction(entityMap, AggregateFunctionEnum.Min, expression)); sqlExpressionContext.Push(subQuery); } // link tables for inline views ((SelectStatement)sqlExpressionContext.Peek()).WhereClause.SearchCondition.Add(new BinaryLogicExpression(new Column(null, subQuery.TableAlias, "ParentId"), BinaryLogicOperator.Equals, linkTableContext.Pop() as Column)); tableContext.Pop(); queryContext.Pop(); } break; case FunctionEnum.Sum: if (firstIsType) { subQuery = (SelectStatement)TransformToSql(function.Path, new string[0], new string[0], true); subQuery.TableAlias = CreateUniqueTableAlias(); if (subQuery is UnionStatement) { SelectStatement select = new SelectStatement(null); select.FromClause.Add(subQuery as Table); subQuery = select; } tableContext.Push(subQuery as Table); _IsFirstAttribute = true; expression = ProcessAttributes((EntityMapping)entityMappingContext.Peek(), function.Path.Identifiers[lastIndex].Value, false, true); subQuery.SelectList = new ExpressionCollection(); subQuery.SelectList.Add(new AggregateFunction(null, AggregateFunctionEnum.Sum, expression)); sqlExpressionContext.Push(subQuery); } else { currentTable = new TableSource(entityMap, ((TableSource)tableContext.Peek()).TableName, CreateUniqueTableAlias()); tableContext.Push(currentTable); queryContext.Push(subQuery); ConvertToSQL(function.Path, false, true, true); expression = ProcessAttributes(entityMap, function.Path.Identifiers[lastIndex].Value, false, true); subQuery = (SelectStatement)queryContext.Peek(); if (subQuery.GetType() == typeof(UnionStatement)) { SelectStatement sel = new SelectStatement(null); subQuery.TableAlias = CreateUniqueTableAlias(); sel.FromClause.Add(subQuery); sel.SelectList = new ExpressionCollection(); sel.SelectList.Add(new AggregateFunction(entityMap, AggregateFunctionEnum.Sum, expression)); sqlExpressionContext.Push(sel); } else { subQuery.SelectList = new ExpressionCollection(); subQuery.SelectList.Add(new AggregateFunction(entityMap, AggregateFunctionEnum.Sum, expression)); sqlExpressionContext.Push(subQuery); } // link tables for inline views ((SelectStatement)sqlExpressionContext.Peek()).WhereClause.SearchCondition.Add(new BinaryLogicExpression(new Column(null, subQuery.TableAlias, "ParentId"), BinaryLogicOperator.Equals, linkTableContext.Pop() as Column)); tableContext.Pop(); queryContext.Pop(); } break; } _ExprLevel.Pop(); }
/// <summary> /// Process an attribute like following : /// Person[Brother.Kind.Name = 'nice'] /// </summary> /// <returns>The column corresponding to the required attribute, i.e. : Name</returns> public ISQLExpression ProcessReferenceAttribute(Path path, EntityMapping baseEntity, string[] references, string attributeName) { bool firstIsType = ((int)_ExprLevel.Peek() == EXPR); _ExprLevel.Push(_ExprLevel.Peek()); SelectStatement subQuery = new SelectStatement(baseEntity); int lastIndex = path.Identifiers.Count - 1; int referenceCounter = 0; if (!firstIsType) { for (int index = 0; index < lastIndex; index++) { string refName = path.Identifiers[index].Value; ReferenceMapping refeMap = baseEntity.References[refName]; // If refeMap == null, cannot find the reference in the child // Then try to get it from parent types if (refeMap == null) { Evaluant.Uss.Models.Entity current = Model.GetEntity(baseEntity.Type); if (refeMap == null) { while (Model.GetParent(current) != null) { current = Model.GetParent(current); refeMap = _Mapping.Entities[current.Type].References[refName]; if (refeMap != null) break; } } } if (refeMap == null) throw new SqlMapperException(string.Concat("Cannot find the reference", refName, " from the entity ", baseEntity.Type)); referenceCounter += 1; //entityMap = _Mapping.Entities.GetEntity(refeMap.EntityChild); } } TableSource currentTable = new TableSource(baseEntity, baseEntity.Table, CreateUniqueTableAlias()); tableContext.Push(currentTable); queryContext.Push(subQuery); bool overrideId = false; if (referenceCounter > 1) overrideId = true; ConvertToSQL(path, false, true, true, overrideId); entityMappingContext.Pop(); subQuery = (SelectStatement)queryContext.Peek(); //// the exists function just need ids fields //// do not list attribute field to avoid problems with data type fields (text, ntext, image for sql server) //// Remove none needed selected item, according to the path //// no references: keep Type, Id (2 fields) //// references: keep Type, IdParent, Id (3 fields) int keepFieldNb = (path.Identifiers.Count == 1) ? 2 : 3; if (subQuery is UnionStatement) { foreach (SelectStatement select in ((UnionStatement)subQuery).SelectExpressions) { for (int i = select.SelectList.Count - 1; i >= keepFieldNb; i--) select.SelectList.RemoveAt(i); // link tables for inline views select.WhereClause.SearchCondition.Add(new BinaryLogicExpression(linkTableContext.Pop() as Column, BinaryLogicOperator.Equals, linkTableContext.Pop() as Column)); } } else { for (int i = subQuery.SelectList.Count - 1; i >= keepFieldNb; i--) subQuery.SelectList.RemoveAt(i); // link tables for inline views subQuery.WhereClause.SearchCondition.Add(new BinaryLogicExpression(linkTableContext.Pop() as Column, BinaryLogicOperator.Equals, linkTableContext.Pop() as Column)); } UnionStatement us = subQuery as UnionStatement; if (us != null) { foreach (SelectStatement s in us.SelectExpressions) { s.SelectList.Clear(); s.SelectList.Add(new Column(null, s.TableAlias, attributeName)); } } else { subQuery.SelectList.Clear(); subQuery.SelectList.Add(new Column(null, attributeName, subQuery.TableAlias)); } //subQuery.SelectedAllColumns = true; //expression = new ExistsPredicate(subQuery); //sqlExpressionContext.Push(subQuery); tableContext.Pop(); queryContext.Pop(); _ExprLevel.Pop(); //return expression; return subQuery; }
public void ProcessEntity(Identifier ident, bool isInRef) { // Restore current entity mapping context EntityMapping entityMapping = (EntityMapping)entityMappingContext.Peek(); // Initialization Table currentTable = new TableSource(entityMapping, entityMapping.Table, CreateUniqueTableAlias()); Column currentItem = new Column(entityMapping.Ids[0], currentTable.TableAlias, entityMapping.GetIdField(entityMapping.Ids[0]), entityMapping.GetIdFieldAs(entityMapping.Ids[0])); SelectStatement currentQuery = new SelectStatement(entityMapping); if (!isInRef) currentQuery.TableAlias = currentTable.TableAlias; // Save current context tableContext.Push(currentTable); sqlExpressionContext.Push(currentItem); queryContext.Push(currentQuery); if (entityMapping.DiscriminatorField != null && !isInRef) { InPredicate ip = new InPredicate(new Column(entityMapping, currentTable.TableAlias, entityMapping.DiscriminatorField)); string parentType = entityMapping.Type; if (_BaseType != null && _BaseType != parentType) { Evaluant.Uss.Models.Entity parentEntity = Model.GetEntity(_BaseType); while (Model.GetParent(parentEntity) != null) parentEntity = Model.GetParent(parentEntity); parentType = parentEntity.Type; } //Evaluant.Uss.Models.Entity parentType = Model.GetEntity(parentType); //Get all the children of the queried type IList children = _Model.GetTree(parentType); ip.SubQueries.Add(new Constant(entityMapping.DiscriminatorValue, DbType.AnsiString)); StringCollection processed = new StringCollection(); foreach (Evaluant.Uss.Models.Entity e in children) { if (e.Type == parentType) continue; EntityMapping current = _Mapping.Entities[e.Type, true]; string currentType = current.DiscriminatorValue; if (processed.Contains(currentType)) continue; processed.Add(currentType); ip.SubQueries.Add(new Constant(currentType, DbType.AnsiString)); } currentQuery.WhereClause.SearchCondition.Add(ip); } // Process constraint : an attribute constraint can modify the context if (ident.Constraint != null) { int stackSizeBefore = entityMappingContext.Count; ProcessConstraint(ident.Constraint); int stackSizeAfter = entityMappingContext.Count; for (int i = stackSizeAfter - 1; i > stackSizeBefore - 1; i--) { entityMappingContext.Pop(); entityModelContext.Pop(); } } }
public virtual void Visit(TableSource table) { //if (string.IsNullOrEmpty(schema)) _Query.Append(FormatAttribute(table.TableName)).Append(SPACE); //else //_Query.Append(FormatAttribute(schema + DBDialect.DOT + table.TableName)).Append(SPACE); if (table.TableAlias != String.Empty) _Query.Append(SPACE).Append(FormatTableAlias(table.TableAlias)).Append(SPACE); }