Beispiel #1
0
        public override void Bind(BindContext context)
        {
            Debug.Assert(IsLeaf());
            Debug.Assert(tabRef_ is null);
            Debug.Assert(tabName_ == tableName_());

            // if table name is not given, search through all tablerefs
            isParameter_ = false;
            tabRef_      = context.GetTableRef(tabName_, colName_);

            // we can't find the column in current context, so it could an outer reference
            if (tabRef_ is null)
            {
                // can't find in my current context, try my ancestors levels up: order is important
                // as we are matching naming with the order closest first
                //    ... from A ... ( from A where exists (... from B where b1 > a.a1))
                // so a.a1 matches the inner side A.
                //
                BindContext parent = context;
                while ((parent = parent.parent_) != null)
                {
                    tabRef_ = parent.GetTableRef(tabName_, colName_);
                    if (tabRef_ != null)
                    {
                        // we are actually switch the context to parent, whichTab_ is not right ...
                        isParameter_ = true;
                        tabRef_.colRefedBySubq_.Add(this);

                        // mark myself a correlated query and remember whom I am correlated to
                        var mystmt = context.stmt_ as SelectStmt;
                        mystmt.isCorrelated_ = true;
                        mystmt.correlatedWhich_.Add(parent.stmt_ as SelectStmt);

                        context = parent;
                        break;
                    }
                }
                if (tabRef_ is null)
                {
                    throw new SemanticAnalyzeException($"can't bind column '{colName_}' to table");
                }
            }

            // we have identified the tableRef this belongs to, make sure outputName not conflicting
            // Eg. select c1 as c2, ... from c
            if (!outputName_.Equals(colName_) &&
                tabRef_.LocateColumn(outputName_) != null)
            {
                throw new SemanticAnalyzeException($"conflicting output name {outputName_} is not allowed");
            }

            Debug.Assert(tabRef_ != null);
            if (!isParameter_)
            {
                Debug.Assert(tableRefs_.Count == 0);
                tableRefs_.Add(tabRef_);
            }
            // FIXME: we shall not decide ordinal_ so early but if not, hard to handle outerref
            ordinal_ = context.ColumnOrdinal(tabRef_.alias_, colName_, out ColumnType type);
            type_    = type;
            markBounded();
        }