private static void ProcessMaximized(SemqContext context, Predicate predicate, ref Chainer query) { var ix1 = context.GetNewIndex(); var ix2 = context.GetNewIndex(); var self = predicate.Subject; context.SetIndex(self); var maximizedExpression = predicate.MaximizedExpression; var ordered = predicate.MaximizedType == MaximizationType.Min ? new OrderedChainer(maximizedExpression, SortOrder.Asc) : new OrderedChainer(maximizedExpression, SortOrder.Desc); var root = new InternalNode(self); query = root.GetDesigner() .From(Designer.GetNewDesigner() .From(((ISelect)query).Select(), root).As(ix1) .OrderBy(ordered) .Select().TopWithTies(predicate.MaximizedTop) , root ).As(ix2); self.ChangeIndex(ix2); }
internal static IOpenView SelectFromSemantic(ISemantic query) { var subject = ((ISemantic)query).Subject; var context = new SemqContext(subject, subject.QueryRoot); return(((ISelect)query.Translate(context, null)).Select()); }
Chainer ISemantic.Translate(SemqContext context, DbNode predecessor) { if (context == null) { throw new QueryTalkException(this, QueryTalkExceptionType.NullArgumentInnerException, "context = null", "InternalNode.ISemantic.Translate"); } if (predecessor == null) { throw new QueryTalkException(this, QueryTalkExceptionType.NullArgumentInnerException, "predecessor = null", "InternalNode.ISemantic.Translate"); } context.SetIndex(this); var from = GetDesigner().From(new Table(Map.Name, new AliasAs(Index))); if (!((IPredicate)this).HasPredicate) { return(from); } var predicate = ((IPredicate)this).Predicates[0]; var relation = DbMapping.GetRelation(predecessor.SynonymOrThis.NodeID, NodeID, DB3.Default); var relationExpression = relation.BuildRelation(predecessor.SynonymOrThis.NodeID, predecessor.Index, Index).E(); if (predicate.PredicateType == PredicateType.Cartesian) { var innerNode = ((ISemantic)predicate).Subject; context.SetIndex(innerNode); innerNode.QueryRoot = context.Subject; var innerJoinAs = from .InnerJoin((IOpenView)innerNode) .As(innerNode.Index); var joinRelation = DbMapping.GetRelation(NodeID, innerNode.SynonymOrThis.NodeID, DB3.Default); var joinExpression = joinRelation.BuildRelation(NodeID, Index, innerNode.Index).E(); var on = innerJoinAs .On(joinExpression); if (IsFinalizeable) { return(on.Where(relationExpression)); } else { return(on); } } else { return((Chainer)from.WhereExists( (INonSelectView) ((ISemantic)predicate).Translate(context, this), true) .AndWhere(relationExpression, true)); } }
internal static void ProcessSelfPredicate(SemqContext context, DbNode currentNode, Predicate predicate, ref Chainer query) { if (predicate.PredicateType == PredicateType.Maximized) { ProcessMaximized(context, predicate, ref query); } else { ProcessExpressionSQL(currentNode, predicate, ref query); } }
/// <summary> /// Sets the inner node of the graph instance. /// </summary> /// <param name="context">A semantic context.</param> /// <param name="innerNode">The inner node.</param> protected void SetInnerNode(SemqContext context, DbNode innerNode) { if (context == null) { throw new QueryTalkException(this, QueryTalkExceptionType.NullArgumentInnerException, "context = null", "DbGraphBase.SetInnerNode"); } _innerNode = innerNode; context.SetGraphIndex(_innerNode); }
private static void ProcessQuantified(SemqContext context, Predicate predicate, ref Chainer query) { var body = TranslatePredicate(context, predicate); if (query is IWhere) { query = ((IWhere)query).WhereQuantified(body, predicate.Sign, predicate); } else { query = ((ConditionChainer)query).WhereQuantified(body, predicate.Sign, predicate); } }
private static void ProcessExistential(SemqContext context, Predicate predicate, ref Chainer query) { var body = TranslatePredicate(context, predicate); if (query is IWhere) { query = ((IWhere)query).WhereExists(body, predicate.Sign, predicate.PredicateGroup); } else { query = ((ConditionChainer)query).WhereExists(body, predicate.Sign, predicate); } }
internal static void TranslateGraph(IGraph graph, SemqContext context, IGraph predecessor) { if (predecessor == null) { Translate.TranslateGraphNode(graph, context, null, context.Subject); } while (graph != null) { ((IGraph)graph).Translate(context, predecessor); graph = graph.Next; } }
/// <summary> /// Executes the table-valued function returning a strongly typed result set. /// </summary> /// <param name="client">A client assembly.</param> /// <param name="arguments">Are the arguments to pass.</param> protected Result <TNode> GoFunc(System.Reflection.Assembly client, params FunctionArgument[] arguments) { return(PublicInvoker.Call <Result <TNode> >(() => { _arguments = arguments; var context = new SemqContext((DbNode)this); var query = ((ISelect)((ISemantic)this).Translate(context, null)) .Select(); Mapper.SetSql(((IEndProc)query).EndProcInternal().Sql); var connectable = Reader.GetConnectable(client, Mapper); return Reader.LoadTable <TNode>(connectable, null, true); })); }
/// <summary> /// Returns the inner node of the graph instance. /// </summary> /// <param name="context">A semantic context.</param> protected DbNode GetInnerNode(SemqContext context) { if (context == null) { throw new QueryTalkException(this, QueryTalkExceptionType.NullArgumentInnerException, "context = null", "DbGraphBase.GetInnerNode"); } if (_innerNode != null) { return(_innerNode); } else { var innerNode = InnerGraph.Subject; context.SetGraphIndex(innerNode); return(innerNode); } }
internal static void TranslateGraphNode(IGraph graph, SemqContext context, DbNode predecessor, DbNode node, bool isLeafNode = false) { var isSubject = (predecessor == null); node = node.Root; context.SetGraphIndex(node); Chainer translatedNode; Designer root; if (isSubject) { root = new InternalRoot(node); } else { root = context.TranslatedGraph.GetRoot(); node.IsFinalizeable = false; } // translate node only // important: // The node should be translated before the graph processing begins in order that to obtain the appropriate index. translatedNode = ((ISemantic)node).Translate(context, predecessor); StringBuilder nodeTableVar = null; // create table variable storage except for the last leaf node which does not need a table variable if (!isLeafNode) { TranslateGraphDeclareTable(node, root, out nodeTableVar); } // finish the node query translation as part of a graph if (isSubject) { TranslateGraphSubject(context, node, root, translatedNode, nodeTableVar); } else { TranslateGraphRelated(graph, context, predecessor, node, translatedNode, nodeTableVar); } }
internal static void ProcessPredicate(SemqContext context, Predicate predicate, ref Chainer query) { switch (predicate.PredicateType) { case PredicateType.Existential: ProcessExistential(context, predicate, ref query); break; case PredicateType.Quantified: ProcessQuantified(context, predicate, ref query); break; case PredicateType.TopQuantified: ProcessTopQuantified(context, predicate, ref query); break; case PredicateType.Maximized: ProcessMaximized(context, predicate, ref query); break; } }
internal static DbNode ProcessIntermediate(SemqContext context, Predicate predicate, DbNode innerNode, Link link) { var intermediate = new InternalNode(link.Intermediate); context.AddNode(intermediate); intermediate.IsFinalizeable = predicate.IsFinalizeable; if (predicate.PredicateType == PredicateType.Quantified || predicate.PredicateType == PredicateType.TopQuantified) { ((IPredicate)intermediate).AddPredicate(PredicateType.Cartesian, innerNode); } else { ((IPredicate)intermediate).AddPredicate(PredicateType.Existential, innerNode); } predicate.Sentence = (ISemantic)intermediate; return(intermediate); }
private static void TranslateGraphSubject(SemqContext context, DbNode node, Designer root, Chainer translatedNode, StringBuilder nodeTableVar) { var ix1 = node.Index; var ix2 = context.GetNewIndex(); var columnArguments = node.Map.GetKeyColumns(node.Index); var nodeTableVarName = GetTableVarName(ix1); var subjectQuery = ((ISelect)translatedNode) .Select(columnArguments) .Insert(nodeTableVarName) .EndSnipInternal(); context.TranslatedGraph = root.GetDesigner() .Inject(nodeTableVar.ToString()) .Inject(subjectQuery) .From(node.Map.Name).As(ix1) .InnerJoin(nodeTableVarName).As(ix2).On(node.Map.BuildSelfRelation(ix1, ix2)) .Select(node.Map.GetColumns(ix1)) .End(); }
private static INonSelectView TranslatePredicate(SemqContext context, Predicate predicate) { return((INonSelectView)((ISemantic)predicate).Translate(context, predicate.Subject)); }
Chainer ISemantic.Translate(SemqContext context, DbNode predecessor) { return(Translate.TranslateNode(context, predecessor, this)); }
// translate related table private static void TranslateGraphRelated(IGraph graph, SemqContext context, DbNode predecessor, DbNode related, Chainer translatedNode, StringBuilder relatedTableVar) { // try find link var link = DbMapping.TryFindPredicateLink(predecessor, related.Root, Text.Method.With); if (link.HasIntermediate) { ThrowWithRelatedNotFound(graph, related.Root); } // get FK var foreignKey = related.GetFK(); foreignKey = foreignKey.Coalesce(link.DefaultForeignKey); // set RX var relation = context.AddGraphPair(foreignKey, predecessor, related, link); // add comment context.TranslatedGraph.Comment(String.Format("{0} {1} of {2} ({3}->{4})", Text.Free.GraphComment, related.Name, predecessor.Name, predecessor.RX, related.RX)); var predecessorTableVarName = GetTableVarName(predecessor.Index); var relatedTableVarName = GetTableVarName(related.Index); var keyColumns = related.Map.GetKeyColumns(related.Index); var ix1 = context.GetNewIndex(); var ix2 = context.GetNewIndex(); var ix3 = context.GetNewIndex(); // append the predicate if (translatedNode is ConditionChainer) { translatedNode = ((IWhereAnd)translatedNode) .AndExists(new InternalRoot(related).GetDesigner() .From(predecessorTableVarName).As(ix1) .Where(relation.BuildRelation(related.NodeID, related.Index, ix1))); } else { translatedNode = ((IWhere)translatedNode) .WhereExists(new InternalRoot(related).GetDesigner() .From(predecessorTableVarName).As(ix1) .Where(relation.BuildRelation(related.NodeID, related.Index, ix1))); } // inject related table query into the subject query if (relatedTableVar != null) { context.TranslatedGraph .Inject(relatedTableVar.ToString()) .Inject((((ISelect)translatedNode) .Select(keyColumns) .Insert(GetTableVarName(related.Index))) .EndSnipInternal()) .From(related.Map.Name).As(ix2) .InnerJoin(relatedTableVarName).As(ix3).On(related.Map.BuildSelfRelation(ix2, ix3)) .Select(related.Map.GetColumns(ix2)); } // leaf nodes: else { var allColumns = related.Map.GetColumns(related.Index); context.TranslatedGraph .Inject((((ISelect)translatedNode).Select(allColumns)).EndSnipInternal()); } }
Chainer ISemantic.Translate(SemqContext context, DbNode predecessor) { var innerNode = ((ISemantic)this).Subject; return(((ISemantic)innerNode).Translate(context, predecessor)); }
// General translation method for the database (table) node. internal static Chainer TranslateNode(SemqContext context, DbNode predecessor, DbNode node) { var currentNode = node.Root; if (context == null) { context = new SemqContext(currentNode); } context.AddNode(currentNode); currentNode.CheckReuseAndThrow(); context.SetIndex(currentNode); Chainer query = Translate.CreateQueryFromSubject(currentNode); if (currentNode.HasExpression) { query.ExpressionGroupType = ExpressionGroupType.BeginEnd; Translate.ProcessExpression(currentNode, null, ref query); } else { currentNode.SetAsUsed(); } Translate.ConvertChainIntoPredicate(currentNode); if (((IPredicate)currentNode).HasPredicate) { Predicate prevPredicate = null; var predicates = ((IPredicate)currentNode).Predicates; var pix = 0; foreach (var predicate in predicates) { SetExpressionGrouping(query, predicates, predicate, ref pix); CheckHavingPredicateAndThrow(predicate, ref prevPredicate); var innerNode = ((ISemantic)predicate).Subject; if (innerNode != null) { context.AddNode(innerNode); if (CheckSelfPredicate(currentNode, innerNode)) { innerNode = innerNode.BreakChain(); predicate.Sentence = (ISemantic)innerNode; } else if (innerNode.Equals(currentNode) && innerNode.HasExpression) { // let the predicate subject have the same level as its caller innerNode.ChangeIndex(currentNode.Index); Translate.ProcessExpression(innerNode, predicate, ref query); continue; } // get link var link = DbMapping.TryFindPredicateLink(currentNode, innerNode); // process intermediate node DbNode intermediate = null; if (link.HasIntermediate) { intermediate = Translate.ProcessIntermediate(context, predicate, innerNode, link); } // process a simple foreign key (if possible) else if (Translate.ProcessSimpleForeignKey(currentNode, innerNode, predicate, link, ref query)) { CheckQuantifierAndThrow(currentNode, innerNode, intermediate, predicate); continue; } CheckQuantifierAndThrow(currentNode, innerNode, intermediate, predicate); Translate.ProcessPredicate(context, predicate, ref query); } else { Translate.ProcessSelfPredicate(context, currentNode, predicate, ref query); } } } if (predecessor != null) { Translate.Finalize(predecessor, currentNode, ref query); } if (((IPredicate)currentNode).PredicateGroupLevel != 0) { PredicateGroup.ThrowInvalidPredicateGroupingException((DbNode)currentNode); } return(query); }
private static void ProcessTopQuantified(SemqContext context, Predicate predicate, ref Chainer query) { // manually create new table indexes var ix1 = context.GetNewIndex(); var ix2 = context.GetNewIndex(); var ix3 = context.GetNewIndex(); var ix4 = context.GetNewIndex(); // get relation between the subject of the predicate and its inner node var subject = predicate.Subject; var self = subject.SynonymOrThis.Map.Name; var innerNode = ((ISemantic)predicate).Subject; var link = DbMapping.TryFindPredicateLink(subject, innerNode); var foreignKey = innerNode.GetFK(); var relation = link.TryGetRelation(foreignKey); var relationExpression = relation.BuildRelation(subject.NodeID, ix1, ix2).E(); var count = Designer.Identifier(ix4.ToString(), Text.Reserved.CountColumnReserved); // get columns of inner table A1 List <Column> columnsA1 = new List <Column>(); columnsA1.AddRange(subject.SynonymOrThis.Map.GetRKColumns(ix4)); columnsA1.Add(count); // get columns of inner table A2 List <Column> columnsA2 = new List <Column>(); columnsA2.AddRange(subject.SynonymOrThis.Map.GetRKColumns(ix1)); columnsA2.Add(Designer.CountBig().As(Text.Reserved.CountColumnReserved)); // build self-relation of a Subject var selfRelation = subject.SynonymOrThis.Map.BuildSelfRelation(subject.Index, ix3); // translate predicate (without finalization) // attention: // Do not move this line upper, before tableB assignment because after the translation // the node chain gets split and tableB is not assigned the correct node if the predicate // is translated before the assignment takes place. var translatedPredicate = ((ISelect)TranslatePredicate(context, predicate)); // get columns of inner table B2 (subject of a predicate) List <Column> columnsB2 = new List <Column>(); if (relation.IsRefTable(innerNode.NodeID)) { columnsB2.AddRange(innerNode.Map.GetRKColumns(innerNode.Index)); } else { columnsB2.AddRange(relation.GetFK(innerNode.Index)); } // create TopQuantified body var body = Designer.GetNewDesigner() .From(Designer.GetNewDesigner() .From(Designer.GetNewDesigner() .From(self).As(ix1) .InnerJoin(translatedPredicate.Select(columnsB2.ToArray())).As(ix2) // diff .On(relationExpression) .GroupBy(subject.SynonymOrThis.Map.GetGroupBy(ix1)) .Select(columnsA2.ToArray())).As(ix4) .OrderBy(count.AsDesc()) .Select(columnsA1.ToArray()).TopWithTies(predicate.Quantifier.Cardinality) , subject).As(ix3) .Where(selfRelation, predicate.Sign, null); if (query is IWhere) { query = ((IWhere)query).WhereExists(body, predicate.Sign, predicate.PredicateGroup); } else { query = ((ConditionChainer)query).WhereExists(body, predicate.Sign, predicate); } }