github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/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 node.OnConflict.Constraint != "" {
    56  			ctx.WriteString(" ON CONSTRAINT ")
    57  			ctx.FormatNode(&node.OnConflict.Constraint)
    58  		}
    59  		if len(node.OnConflict.Columns) > 0 {
    60  			ctx.WriteString(" (")
    61  			ctx.FormatNode(&node.OnConflict.Columns)
    62  			ctx.WriteString(")")
    63  		}
    64  		if node.OnConflict.ArbiterPredicate != nil {
    65  			ctx.WriteString(" WHERE ")
    66  			ctx.FormatNode(node.OnConflict.ArbiterPredicate)
    67  		}
    68  		if node.OnConflict.DoNothing {
    69  			ctx.WriteString(" DO NOTHING")
    70  		} else {
    71  			ctx.WriteString(" DO UPDATE SET ")
    72  			ctx.FormatNode(&node.OnConflict.Exprs)
    73  			if node.OnConflict.Where != nil {
    74  				ctx.WriteByte(' ')
    75  				ctx.FormatNode(node.OnConflict.Where)
    76  			}
    77  		}
    78  	}
    79  	if HasReturningClause(node.Returning) {
    80  		ctx.WriteByte(' ')
    81  		ctx.FormatNode(node.Returning)
    82  	}
    83  }
    84  
    85  // DefaultValues returns true iff only default values are being inserted.
    86  func (node *Insert) DefaultValues() bool {
    87  	return node.Rows.Select == nil
    88  }
    89  
    90  // OnConflict represents an `ON CONFLICT (columns) WHERE arbiter DO UPDATE SET
    91  // exprs WHERE where` clause.
    92  //
    93  // The zero value for OnConflict is used to signal the UPSERT short form, which
    94  // uses the primary key for as the conflict index and the values being inserted
    95  // for Exprs.
    96  type OnConflict struct {
    97  	// At most one of Columns and Constraint will be set at once.
    98  	// Columns is the list of arbiter columns, if set, that the user specified
    99  	// in the ON CONFLICT (columns) list.
   100  	Columns NameList
   101  	// Constraint is the name of a table constraint that the user specified to
   102  	// get the list of arbiter columns from, in the ON CONFLICT ON CONSTRAINT
   103  	// form.
   104  	Constraint       Name
   105  	ArbiterPredicate Expr
   106  	Exprs            UpdateExprs
   107  	Where            *Where
   108  	DoNothing        bool
   109  }
   110  
   111  // IsUpsertAlias returns true if the UPSERT syntactic sugar was used.
   112  func (oc *OnConflict) IsUpsertAlias() bool {
   113  	return oc != nil && oc.Columns == nil && oc.Constraint == "" &&
   114  		oc.ArbiterPredicate == nil && oc.Exprs == nil && oc.Where == nil && !oc.DoNothing
   115  }