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

     1  // Copyright 2022 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 plan
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  
    21  	"github.com/dolthub/go-mysql-server/sql"
    22  )
    23  
    24  // Into is a node to wrap the top-level node in a query plan so that any result will set user-defined or others
    25  // variables given
    26  type Into struct {
    27  	UnaryNode
    28  	IntoVars []sql.Expression
    29  	Dumpfile string
    30  	Outfile  string
    31  
    32  	Charset string
    33  
    34  	FieldsTerminatedBy  string
    35  	FieldsEnclosedBy    string
    36  	FieldsEnclosedByOpt bool
    37  	FieldsEscapedBy     string
    38  
    39  	LinesStartingBy   string
    40  	LinesTerminatedBy string
    41  }
    42  
    43  var _ sql.Node = (*Into)(nil)
    44  var _ sql.CollationCoercible = (*Into)(nil)
    45  
    46  // Default values as defined here: https://dev.mysql.com/doc/refman/8.0/en/load-data.html
    47  const (
    48  	defaultFieldsTerminatedBy  = "\t"
    49  	defaultFieldsEnclosedBy    = ""
    50  	defaultFieldsEnclosedByOpt = false
    51  	defaultFieldsEscapedBy     = "\\"
    52  	defaultLinesStartingBy     = ""
    53  	defaultLinesTerminatedBy   = "\n"
    54  )
    55  
    56  func NewInto(
    57  	child sql.Node,
    58  	variables []sql.Expression,
    59  	outfile, dumpfile string) *Into {
    60  	return &Into{
    61  		UnaryNode: UnaryNode{child},
    62  		IntoVars:  variables,
    63  		Dumpfile:  dumpfile,
    64  		Outfile:   outfile,
    65  
    66  		FieldsTerminatedBy:  defaultFieldsTerminatedBy,
    67  		FieldsEnclosedBy:    defaultFieldsEnclosedBy,
    68  		FieldsEnclosedByOpt: defaultFieldsEnclosedByOpt,
    69  		FieldsEscapedBy:     defaultFieldsEscapedBy,
    70  
    71  		LinesStartingBy:   defaultLinesStartingBy,
    72  		LinesTerminatedBy: defaultLinesTerminatedBy,
    73  	}
    74  }
    75  
    76  // Schema implements the Node interface.
    77  func (i *Into) Schema() sql.Schema {
    78  	// SELECT INTO does not return results directly (only through SQL vars or files),
    79  	// so it's result schema is always empty.
    80  	return nil
    81  }
    82  
    83  func (i *Into) IsReadOnly() bool {
    84  	return i.Child.IsReadOnly()
    85  }
    86  
    87  func (i *Into) String() string {
    88  	p := sql.NewTreePrinter()
    89  	var vars = make([]string, len(i.IntoVars))
    90  	for j, v := range i.IntoVars {
    91  		vars[j] = fmt.Sprintf(v.String())
    92  	}
    93  	_ = p.WriteNode("Into(%s, Outfile %s, Dumpfile %s)", strings.Join(vars, ", "), i.Outfile, i.Dumpfile)
    94  	_ = p.WriteChildren(i.Child.String())
    95  	return p.String()
    96  }
    97  
    98  func (i *Into) DebugString() string {
    99  	p := sql.NewTreePrinter()
   100  	var vars = make([]string, len(i.IntoVars))
   101  	for j, v := range i.IntoVars {
   102  		vars[j] = sql.DebugString(v)
   103  	}
   104  	_ = p.WriteNode("Into(%s, Outfile %s, Dumpfile %s)", strings.Join(vars, ", "), i.Outfile, i.Dumpfile)
   105  	_ = p.WriteChildren(sql.DebugString(i.Child))
   106  	return p.String()
   107  }
   108  
   109  func (i *Into) WithChildren(children ...sql.Node) (sql.Node, error) {
   110  	if len(children) != 1 {
   111  		return nil, sql.ErrInvalidChildrenNumber.New(i, len(children), 1)
   112  	}
   113  	ni := *i
   114  	ni.Child = children[0]
   115  	return &ni, nil
   116  }
   117  
   118  // CheckPrivileges implements the interface sql.Node.
   119  func (i *Into) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool {
   120  	return i.Child.CheckPrivileges(ctx, opChecker)
   121  }
   122  
   123  // CollationCoercibility implements the interface sql.CollationCoercible.
   124  func (i *Into) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) {
   125  	return sql.GetCoercibility(ctx, i.Child)
   126  }
   127  
   128  // WithExpressions implements the sql.Expressioner interface.
   129  func (i *Into) WithExpressions(exprs ...sql.Expression) (sql.Node, error) {
   130  	if len(exprs) != len(i.IntoVars) {
   131  		return nil, sql.ErrInvalidChildrenNumber.New(i, len(exprs), len(i.IntoVars))
   132  	}
   133  	ni := *i
   134  	ni.IntoVars = exprs
   135  	return &ni, nil
   136  }
   137  
   138  // Expressions implements the sql.Expressioner interface.
   139  func (i *Into) Expressions() []sql.Expression {
   140  	return i.IntoVars
   141  }