internal string TryGetTableAlias(string alias) { TableChainer ctable = GetPrevTable(Statement.StatementIndex); if (alias == null) { if (ctable != null && ctable is FromChainer) { return(ctable.Alias.Name); } } else { while (ctable != null) { if (ctable != null && ctable.Alias.Name == alias) { return(alias); } ctable = ctable.GetPrevTable(Statement.StatementIndex); } } Throw(QueryTalkExceptionType.TargetTableNotFound, String.Format("target alias = {0}", alias ?? Text.ClrNull)); return(null); }
private string _InjectColumnGraph(DbColumn column, TableChainer bestMatchTable, int bestMatchIndex) { if (_lastJoinTable != null) { _targets.Add(_lastJoinTable); _lastJoinTable = null; // do reset after the use } // move to the best match table in the column graph var node = column.Parent.Root; while (bestMatchIndex > 1) { node = node.Next; --bestMatchIndex; } // target table to join with var target = bestMatchTable; // loop through the rest of the unmatched tables in the column graph while (node != null) { node = node.Next; if (node != null) { target = _InjectJoinBy(node, target.Alias.Name); } } return(target.Alias.Name); }
// Get target table by alias. // anticipated: // If alias is not given, then the target is the first table - which must be FromChainer. private TableChainer GetTarget(ref string alias) { TableChainer ctable = GetPrevTable(Statement.StatementIndex); if (alias == null) { if (ctable is FromChainer) { alias = ctable.Alias.Name; return(ctable); } return(null); } while (ctable != null) { // case-sensitive comparison if (ctable.Alias.Name.EqualsCS(alias)) { return(ctable); } ctable = ctable.GetPrevTable(Statement.StatementIndex); } return(null); // not found }
private string ProcessColumnAuto(DbColumn column) { TableChainer bestMatchTable = null; int bestMatchIndex = 0; foreach (var table in _tables) { if (!table.HasNode) { continue; } // node comparison if (column.JoinGraph == table.Node.NodeID.ToString()) { return(table.Alias.Name); } // join graph comparison if (column.JoinGraph == table.JoinGraph) { return(table.Alias.Name); } // check the partial match var tableJoinParts = table.JoinGraph.Split(new char[] { Text.DotChar }); var columnJoinParts = column.JoinGraph.Split(new char[] { Text.DotChar }); if (tableJoinParts.Length < columnJoinParts.Length) { if (column.JoinGraph.IndexOf(table.JoinGraph) == 0) { // best match condition if (bestMatchIndex < table.JoinGraphNodeCount) { bestMatchTable = table; bestMatchIndex = table.JoinGraphNodeCount; } } } } // perfect match is not found: // allow nested db columns that are part of the SEMQ // example: // ...Whose(s.Address.City.Country.Name.NotEqualTo(s.Country.Name)) if (column.RootSubject != null) { return(column.RootSubject.Index.ToString()); } // inject column graph if (bestMatchIndex != 0) { return(_InjectColumnGraph(column, bestMatchTable, bestMatchIndex)); } // no match is found (& bestMatchIndex == 0) throw JoinerColumnNotBoundException(column); }
private static Expression _GetMappedExpression(TableChainer source, TableChainer target, DB3 foreignKey) { if (foreignKey.IsDefault) { foreignKey = source.Node.GetFK(); } var joinRelation = DbMapping.GetRelation(target.Node.Root.SynonymOrThis.NodeID, source.Node.Root.SynonymOrThis.NodeID, foreignKey, Text.Method.By); if (foreignKey.IsDefault) { foreignKey = joinRelation.ForeignKey; } // determine join operator (for .Join method only) if (source is SemqJoinChainer && !joinRelation.IsInnerJoin(target.Node.Root.SynonymOrThis.NodeID)) { ((SemqJoinChainer)source).IsLeftOuterJoin = true; } // foreign key table = this if (foreignKey.TableID.Equals(source.Node.NodeID.TableID)) { return(joinRelation.BuildRelation(foreignKey, source.Alias.Name, target.Alias.Name).E()); } // foreign key table = target else { return(joinRelation.BuildRelation(foreignKey, target.Alias.Name, source.Alias.Name).E()); } }
private void AutoJoin(JoinChainer source) { if (!source.HasNode) { throw JoinerException(source, (TableChainer)null, QueryTalkExceptionType.InvalidJoinTable); } bool found = false; TableChainer target = null; var ix = _targets.Count - 1; while (ix >= 0) { target = _targets[ix]; if (CheckAutoTarget(source, target)) { found = true; break; } --ix; } if (!found) { throw JoinerAutoJoinFailedException(source); } var expression = _GetMappedExpression(source, target, DB3.Default); _InjectOn(source, expression); source.AppendJoinGraph(target.JoinGraph); }
private QueryTalkException JoinerException(TableChainer source, string alias, QueryTalkExceptionType exceptionType) { return(new QueryTalkException(this, exceptionType, String.Format("joining table = {0} AS {1}{2} alias of target table = {3}", source.TableArgument.Build(_buildContext, _buildArgs), Filter.Delimit(source.Alias.Name), Environment.NewLine, Filter.Delimit(alias)), Text.Method.By)); }
private QueryTalkException JoinerAutoJoinFailedException(TableChainer source) { if (source.HasNode) { return(new QueryTalkException(this, QueryTalkExceptionType.AutoJoinFailed, String.Format("joining table = {0} AS {1}", source.Node.Root.Name, Filter.Delimit(source.Alias.Name)), Text.Method.Join)); } else { return(new QueryTalkException(this, QueryTalkExceptionType.AutoJoinFailed, String.Format("joining table = {0} AS {1}", source.TableArgument.Build(_buildContext, _buildArgs), Filter.Delimit(source.Alias.Name)), Text.Method.Join)); } }
private static bool CheckAutoTarget(TableChainer source, TableChainer target) { // skip the non-mapped tables if (!target.HasNode) { return(false); } var link = DbMapping.GetLink(source.Node.SynonymOrThis.NodeID, target.Node.SynonymOrThis.NodeID); if (link == null || !link.Intermediate.IsDefault) // intermediate links are not allowed { return(false); } return(true); }
private QueryTalkException JoinerException(TableChainer source, TableChainer target, QueryTalkExceptionType exceptionType) { if (target != null) { return(new QueryTalkException(this, exceptionType, String.Format("joining table {5}= {0} AS {1}{2} target table {6}= {3} AS {4}", source.TableArgument.Build(_buildContext, _buildArgs), Filter.Delimit(source.Alias.Name), Environment.NewLine, target.TableArgument.Build(_buildContext, _buildArgs), Filter.Delimit(target.Alias.Name), (source.Node == null) ? "(INVALID) " : null, (target != null && target.Node == null) ? "(INVALID) " : null ), Text.Method.By)); } else { return(new QueryTalkException(this, exceptionType, String.Format("joining table = {0} AS {1}", source.TableArgument.Build(_buildContext, _buildArgs), Filter.Delimit(source.Alias.Name)), Text.Method.By)); } }
// Adds CTE or table to the corresponding collection. internal void AddTableObject(TableChainer tableObject) { FromChainer cte; if (IsPrevCte(tableObject, out cte)) { QueryTalkException exception = null; if (!(cte.TableArgument.Original is View)) { exception = new QueryTalkException("Query.AddTableObject", QueryTalkExceptionType.InvalidCte, String.Format("CTE = {0}", cte.TableArgument.Original), Text.Method.From); } if (_parts.Count > 1) { exception = new QueryTalkException("Query.AddTableObject", QueryTalkExceptionType.InvalidCte, String.Format("CTE = {0}", cte.TableArgument.Original), Text.Method.From); } if (exception != null) { exception.ObjectName = Root.Name; throw exception; } Clause.Ctes.Add(cte); Clause.Tables.Remove(cte); Clause.Tables.Add(tableObject); } else { Clause.Tables.Add(tableObject); } if (tableObject.Node != null && tableObject.Node.Index > 0) { _tableAlias = tableObject.Node.Index; } }
internal void ProcessJoin() { if (_tables.Count < 2) { if (_tables.Count == 1) { _lastJoinTable = _tables[0]; } return; } for (int i = 1; i < _tables.Count; ++i) { _targets.Add(_tables[i - 1]); if (!(_tables[i] is JoinChainer)) { continue; } var source = (JoinChainer)_tables[i]; if (source.Correlation == JoinCorrelation.On) { continue; } else if (source.Correlation == JoinCorrelation.By) { ByJoin(source); } else { AutoJoin(source); } _lastJoinTable = source; } }
private string ProcessColumnOf(DbColumn column) { // skip non .Select methods if (!(_buildContext.Current is SelectChainer)) { return(column.OfAlias); } bool found = false; TableChainer target = null; foreach (var table in _tables) { if (table.Alias.Name.EqualsCS(column.OfAlias)) { if (!table.HasNode) { throw JoinerColumnNotBoundException(column); } found = true; target = table; break; } } if (!found) { throw JoinerColumnNotBoundException(column); } if (!column.Parent.NodeID.Equals(target.Node.NodeID)) { throw JoinerColumnNotBoundException(column); } return(target.Alias.Name); }