Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        // 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
        }
Example #4
0
        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);
        }
Example #5
0
        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());
            }
        }
Example #6
0
        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);
        }
Example #7
0
 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));
 }
Example #8
0
 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));
     }
 }
Example #9
0
        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);
        }
Example #10
0
 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));
     }
 }
Example #11
0
        // 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;
            }
        }
Example #12
0
        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;
            }
        }
Example #13
0
        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);
        }