github.com/acoshift/pgsql@v0.15.3/pgstmt/insert.go (about)

     1  package pgstmt
     2  
     3  // Insert builds insert statement
     4  func Insert(f func(b InsertStatement)) *Result {
     5  	var st insertStmt
     6  	f(&st)
     7  	return newResult(build(st.make()))
     8  }
     9  
    10  // InsertStatement is the insert statement builder
    11  type InsertStatement interface {
    12  	Into(table string)
    13  	Columns(col ...string)
    14  	OverridingSystemValue()
    15  	OverridingUserValue()
    16  	DefaultValues()
    17  	Value(value ...any)
    18  	Values(values ...[]any)
    19  	Select(f func(b SelectStatement))
    20  
    21  	OnConflict(f func(b ConflictTarget)) ConflictAction
    22  
    23  	// OnConflictDoNothing is the shortcut for
    24  	// OnConflict(func(b ConflictTarget) {}).DoNothing()
    25  	OnConflictDoNothing()
    26  
    27  	// OnConflictIndex is the shortcut for
    28  	// OnConflict(func(b ConflictTarget) {
    29  	//		b.Index(target...)
    30  	// })
    31  	OnConflictIndex(target ...string) ConflictAction
    32  
    33  	// OnConflictOnConstraint is the shortcut for
    34  	// OnConflict(func(b ConflictTarget) {
    35  	//		b.OnConstraint(constraintName)
    36  	// })
    37  	OnConflictOnConstraint(constraintName string) ConflictAction
    38  
    39  	Returning(col ...string)
    40  }
    41  
    42  type ConflictTarget interface {
    43  	Index(target ...string)
    44  	Where(f func(b Cond))
    45  	OnConstraint(constraintName string)
    46  }
    47  
    48  type ConflictAction interface {
    49  	DoNothing()
    50  	DoUpdate(f func(b UpdateStatement))
    51  }
    52  
    53  type insertStmt struct {
    54  	table           string
    55  	columns         parenGroup
    56  	overridingValue string
    57  	defaultValues   bool
    58  	conflict        *conflict
    59  	values          group
    60  	selects         *selectStmt
    61  	returning       group
    62  }
    63  
    64  func (st *insertStmt) Into(table string) {
    65  	st.table = table
    66  }
    67  
    68  func (st *insertStmt) Columns(col ...string) {
    69  	st.columns.pushString(col...)
    70  }
    71  
    72  func (st *insertStmt) OverridingSystemValue() {
    73  	st.overridingValue = "system"
    74  }
    75  
    76  func (st *insertStmt) OverridingUserValue() {
    77  	st.overridingValue = "user"
    78  }
    79  
    80  func (st *insertStmt) DefaultValues() {
    81  	st.defaultValues = true
    82  }
    83  
    84  func (st *insertStmt) Value(value ...any) {
    85  	var x parenGroup
    86  	for _, v := range value {
    87  		x.push(Arg(v))
    88  	}
    89  	st.values.push(&x)
    90  }
    91  
    92  func (st *insertStmt) Values(values ...[]any) {
    93  	for _, value := range values {
    94  		st.Value(value...)
    95  	}
    96  }
    97  
    98  func (st *insertStmt) Select(f func(b SelectStatement)) {
    99  	var x selectStmt
   100  	f(&x)
   101  	st.selects = &x
   102  }
   103  
   104  func (st *insertStmt) OnConflict(f func(b ConflictTarget)) ConflictAction {
   105  	var x conflict
   106  	f(&x)
   107  	st.conflict = &x
   108  	return &st.conflict.action
   109  }
   110  
   111  func (st *insertStmt) OnConflictDoNothing() {
   112  	st.conflict = &conflict{
   113  		action: conflictAction{
   114  			doNothing: true,
   115  		},
   116  	}
   117  }
   118  
   119  func (st *insertStmt) OnConflictIndex(target ...string) ConflictAction {
   120  	return st.OnConflict(func(b ConflictTarget) {
   121  		b.Index(target...)
   122  	})
   123  }
   124  
   125  func (st *insertStmt) OnConflictOnConstraint(constraintName string) ConflictAction {
   126  	return st.OnConflict(func(b ConflictTarget) {
   127  		b.OnConstraint(constraintName)
   128  	})
   129  }
   130  
   131  func (st *insertStmt) Returning(col ...string) {
   132  	st.returning.pushString(col...)
   133  }
   134  
   135  func (st *insertStmt) make() *buffer {
   136  	var b buffer
   137  	b.push("insert")
   138  	if st.table != "" {
   139  		b.push("into", st.table)
   140  	}
   141  	if !st.columns.empty() {
   142  		b.push(&st.columns)
   143  	}
   144  	if st.overridingValue != "" {
   145  		b.push("overriding", st.overridingValue, "value")
   146  	}
   147  	if st.defaultValues {
   148  		b.push("default values")
   149  	}
   150  	if !st.values.empty() {
   151  		b.push("values", &st.values)
   152  	}
   153  	if st.selects != nil {
   154  		b.push(st.selects.make())
   155  	}
   156  	if st.conflict != nil {
   157  		b.push(st.conflict.make())
   158  	}
   159  	if !st.returning.empty() {
   160  		b.push("returning", &st.returning)
   161  	}
   162  
   163  	return &b
   164  }
   165  
   166  type conflict struct {
   167  	targets    []string
   168  	where      cond
   169  	constraint string
   170  	action     conflictAction
   171  }
   172  
   173  func (st *conflict) make() *buffer {
   174  	// on conflict can be one of
   175  	// => ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
   176  	// => ON CONSTRAINT constraint_name
   177  
   178  	var b buffer
   179  
   180  	b.push("on conflict")
   181  
   182  	if len(st.targets) > 0 {
   183  		b.push(parenString(st.targets...))
   184  
   185  		if !st.where.empty() {
   186  			b.push("where", &st.where)
   187  		}
   188  	} else if st.constraint != "" {
   189  		b.push("on constraint", st.constraint)
   190  	}
   191  
   192  	b.push(st.action.make())
   193  
   194  	return &b
   195  }
   196  
   197  func (st *conflict) Index(target ...string) {
   198  	st.targets = append(st.targets, target...)
   199  }
   200  
   201  func (st *conflict) Where(f func(b Cond)) {
   202  	f(&st.where)
   203  }
   204  
   205  func (st *conflict) OnConstraint(constraintName string) {
   206  	st.constraint = constraintName
   207  }
   208  
   209  type conflictAction struct {
   210  	doNothing bool
   211  	doUpdate  *updateStmt
   212  }
   213  
   214  func (st *conflictAction) make() *buffer {
   215  	var b buffer
   216  	if st.doNothing {
   217  		b.push("do nothing")
   218  	}
   219  	if st.doUpdate != nil {
   220  		b.push("do", st.doUpdate.make())
   221  	}
   222  	return &b
   223  }
   224  
   225  func (st *conflictAction) DoNothing() {
   226  	st.doNothing = true
   227  }
   228  
   229  func (st *conflictAction) DoUpdate(f func(b UpdateStatement)) {
   230  	var x updateStmt
   231  	f(&x)
   232  	st.doUpdate = &x
   233  }