package sqimple import ( "context" "database/sql" "fmt" "slices" "strings" ) // https://www.sqlite.org/lang_delete.html type InsertStatement struct { Ctx context.Context DB *sql.DB table InsertTable or string columns []string values []Values selectValues *SelectQuery } func (s *InsertStatement) Args() []any { if s.selectValues != nil { return s.selectValues.Args() } args := []any{} for _, row := range s.values { for _, column := range s.columns { args = append(args, row[column]) } } return args } func (s *InsertStatement) Exec() (sql.Result, error) { if s.DB != nil { if s.Ctx != nil { return s.DB.ExecContext(s.Ctx, s.String(), s.Args()...) } return s.DB.Exec(s.String(), s.Args()...) } return nil, ErrNoDatabase } func (s *InsertStatement) IsValid() bool { if !s.table.IsValid() { return false } return false } func (s *InsertStatement) Columns(columns ...string) *InsertStatement { if s.columns == nil { s.columns = []string{} } for _, column := range columns { if !slices.Contains(s.columns, column) { s.columns = append(s.columns, columns...) } } return s } func (s *InsertStatement) Or(or string) *InsertStatement { s.or = or return s } func (s *InsertStatement) Select(q *SelectQuery) *InsertStatement { s.selectValues = q return s } func (s *InsertStatement) String() string { strs := []string{"insert"} if s.or != "" { strs = append(strs, "or", s.or) } strs = append(strs, s.table.String()) if len(s.columns) > 0 { strs = append(strs, fmt.Sprintf("(%s)", strings.Join(s.columns, ", "))) } if s.selectValues != nil { strs = append(strs, s.selectValues.String()) } else { strs = append(strs, "values") valueStrs := []string{} for range s.values { marks := []string{} for range s.columns { marks = append(marks, "?") } valueStrs = append(valueStrs, fmt.Sprintf("(%s)", strings.Join(marks, ", "))) } strs = append(strs, strings.Join(valueStrs, ", ")) } return strings.Join(strs, " ") } func (s *InsertStatement) Values(values ...Values) *InsertStatement { if s.values == nil { s.values = []Values{} } for _, row := range values { s.values = append(s.values, row) } return s } func Insert(into string) *InsertStatement { s := &InsertStatement{ table: Into(into), } return s }