github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sem/tree/insert.go (about)

     1  // Copyright 2012, Google Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in licenses/BSD-vitess.txt.
     4  
     5  // Portions of this file are additionally subject to the following
     6  // license and copyright.
     7  //
     8  // Copyright 2015 The Cockroach Authors.
     9  //
    10  // Use of this software is governed by the Business Source License
    11  // included in the file licenses/BSL.txt.
    12  //
    13  // As of the Change Date specified in that file, in accordance with
    14  // the Business Source License, use of this software will be governed
    15  // by the Apache License, Version 2.0, included in the file
    16  // licenses/APL.txt.
    17  
    18  // This code was derived from https://github.com/youtube/vitess.
    19  
    20  package tree
    21  
    22  // Insert represents an INSERT statement.
    23  type Insert struct {
    24  	With       *With
    25  	Table      TableExpr
    26  	Columns    NameList
    27  	Rows       *Select
    28  	OnConflict *OnConflict
    29  	Returning  ReturningClause
    30  }
    31  
    32  // Format implements the NodeFormatter interface.
    33  func (node *Insert) Format(ctx *FmtCtx) {
    34  	ctx.FormatNode(node.With)
    35  	if node.OnConflict.IsUpsertAlias() {
    36  		ctx.WriteString("UPSERT")
    37  	} else {
    38  		ctx.WriteString("INSERT")
    39  	}
    40  	ctx.WriteString(" INTO ")
    41  	ctx.FormatNode(node.Table)
    42  	if node.Columns != nil {
    43  		ctx.WriteByte('(')
    44  		ctx.FormatNode(&node.Columns)
    45  		ctx.WriteByte(')')
    46  	}
    47  	if node.DefaultValues() {
    48  		ctx.WriteString(" DEFAULT VALUES")
    49  	} else {
    50  		ctx.WriteByte(' ')
    51  		ctx.FormatNode(node.Rows)
    52  	}
    53  	if node.OnConflict != nil && !node.OnConflict.IsUpsertAlias() {
    54  		ctx.WriteString(" ON CONFLICT")
    55  		if len(node.OnConflict.Columns) > 0 {
    56  			ctx.WriteString(" (")
    57  			ctx.FormatNode(&node.OnConflict.Columns)
    58  			ctx.WriteString(")")
    59  		}
    60  		if node.OnConflict.DoNothing {
    61  			ctx.WriteString(" DO NOTHING")
    62  		} else {
    63  			ctx.WriteString(" DO UPDATE SET ")
    64  			ctx.FormatNode(&node.OnConflict.Exprs)
    65  			if node.OnConflict.Where != nil {
    66  				ctx.WriteByte(' ')
    67  				ctx.FormatNode(node.OnConflict.Where)
    68  			}
    69  		}
    70  	}
    71  	if HasReturningClause(node.Returning) {
    72  		ctx.WriteByte(' ')
    73  		ctx.FormatNode(node.Returning)
    74  	}
    75  }
    76  
    77  // DefaultValues returns true iff only default values are being inserted.
    78  func (node *Insert) DefaultValues() bool {
    79  	return node.Rows.Select == nil
    80  }
    81  
    82  // OnConflict represents an `ON CONFLICT (columns) DO UPDATE SET exprs WHERE
    83  // where` clause.
    84  //
    85  // The zero value for OnConflict is used to signal the UPSERT short form, which
    86  // uses the primary key for as the conflict index and the values being inserted
    87  // for Exprs.
    88  type OnConflict struct {
    89  	Columns   NameList
    90  	Exprs     UpdateExprs
    91  	Where     *Where
    92  	DoNothing bool
    93  }
    94  
    95  // IsUpsertAlias returns true if the UPSERT syntactic sugar was used.
    96  func (oc *OnConflict) IsUpsertAlias() bool {
    97  	return oc != nil && oc.Columns == nil && oc.Exprs == nil && oc.Where == nil && !oc.DoNothing
    98  }