github.com/dolthub/go-mysql-server@v0.18.0/sql/analyzer/resolve_unions.go (about)

     1  // Copyright 2020-2021 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package analyzer
    16  
    17  import (
    18  	"github.com/dolthub/go-mysql-server/sql"
    19  	"github.com/dolthub/go-mysql-server/sql/plan"
    20  	"github.com/dolthub/go-mysql-server/sql/transform"
    21  )
    22  
    23  // resolveUnions resolves the left and right side of a union node in isolation.
    24  func resolveUnions(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Scope, sel RuleSelector) (sql.Node, transform.TreeIdentity, error) {
    25  	if n.Resolved() {
    26  		return n, transform.SameTree, nil
    27  	}
    28  	// Procedures explicitly handle unions
    29  	if _, ok := n.(*plan.CreateProcedure); ok {
    30  		return n, transform.SameTree, nil
    31  	}
    32  
    33  	return transform.Node(n, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) {
    34  		var u *plan.SetOp
    35  		switch n := n.(type) {
    36  		case *plan.SetOp:
    37  			u = n
    38  		default:
    39  			return n, transform.SameTree, nil
    40  		}
    41  		subqueryCtx, cancelFunc := ctx.NewSubContext()
    42  		defer cancelFunc()
    43  
    44  		left, _, err := a.analyzeThroughBatch(subqueryCtx, u.Left(), scope, "default-rules", sel)
    45  		if err != nil {
    46  			return nil, transform.SameTree, err
    47  		}
    48  
    49  		right, _, err := a.analyzeThroughBatch(subqueryCtx, u.Right(), scope, "default-rules", sel)
    50  		if err != nil {
    51  			return nil, transform.SameTree, err
    52  		}
    53  
    54  		ret, err := n.WithChildren(StripPassthroughNodes(left), StripPassthroughNodes(right))
    55  		if err != nil {
    56  			return nil, transform.SameTree, err
    57  		}
    58  		return ret, transform.NewTree, nil
    59  	})
    60  }
    61  
    62  func finalizeUnions(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Scope, sel RuleSelector) (sql.Node, transform.TreeIdentity, error) {
    63  	// Procedures explicitly handle unions
    64  	if _, ok := n.(*plan.CreateProcedure); ok {
    65  		return n, transform.SameTree, nil
    66  	}
    67  
    68  	return transform.Node(n, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) {
    69  		var u *plan.SetOp
    70  		switch n := n.(type) {
    71  		case *plan.SetOp:
    72  			u = n
    73  		case *plan.RecursiveCte:
    74  			// rCTEs behave like unions after default rules
    75  			u = n.Union()
    76  		default:
    77  			return n, transform.SameTree, nil
    78  		}
    79  		subqueryCtx, cancelFunc := ctx.NewSubContext()
    80  		defer cancelFunc()
    81  
    82  		scope.SetJoin(false)
    83  		// TODO we could detect tree modifications here, skip rebuilding
    84  		left, _, err := a.analyzeStartingAtBatch(subqueryCtx, u.Left(), scope, "default-rules", NewFinalizeUnionSel(sel))
    85  		if err != nil {
    86  			return nil, transform.SameTree, err
    87  		}
    88  
    89  		scope.SetJoin(false)
    90  
    91  		right, _, err := a.analyzeStartingAtBatch(subqueryCtx, u.Right(), scope, "default-rules", NewFinalizeUnionSel(sel))
    92  		if err != nil {
    93  			return nil, transform.SameTree, err
    94  		}
    95  
    96  		scope.SetJoin(false)
    97  
    98  		newn, err := n.WithChildren(StripPassthroughNodes(left), StripPassthroughNodes(right))
    99  		if err != nil {
   100  			return nil, transform.SameTree, err
   101  		}
   102  		return newn, transform.NewTree, nil
   103  	})
   104  }