Files
db/exp/insert_test.go
whatandClaude 304d553b3c docs: Add CLAUDE.md with codebase guidance
Create comprehensive documentation for future Claude Code instances working in this repository, including:
- Development commands for testing, building, and code quality
- Core architecture overview of the SQL query builder system
- Directory structure and component explanations
- Testing patterns and conventions
- Key dependencies and their purposes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-27 15:47:28 +08:00

384 lines
12 KiB
Go

package exp_test
import (
"testing"
"git.fsdpf.net/go/db/exp"
"github.com/stretchr/testify/suite"
)
type testAppendableExpression struct {
exp.AppendableExpression
sql string
args []interface{}
clauses exp.SelectClauses
}
func newTestAppendableExpression(sql string, args []interface{}) exp.AppendableExpression {
return &testAppendableExpression{sql: sql, args: args}
}
func (tae *testAppendableExpression) Expression() exp.Expression {
return tae
}
func (tae *testAppendableExpression) GetClauses() exp.SelectClauses {
return tae.clauses
}
func (tae *testAppendableExpression) Clone() exp.Expression {
return tae
}
type insertExpressionTestSuite struct {
suite.Suite
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withDifferentRecordTypes() {
type testRecord struct {
C string `db:"c"`
}
type testRecord2 struct {
C string `db:"c"`
}
_, err := exp.NewInsertExpression(
testRecord{C: "v1"},
exp.Record{"c": "v2"},
)
iets.EqualError(err, "db: rows must be all the same type expected exp_test.testRecord got exp.Record")
_, err = exp.NewInsertExpression(
testRecord{C: "v1"},
testRecord2{C: "v2"},
)
iets.EqualError(err, "db: rows must be all the same type expected exp_test.testRecord got exp_test.testRecord2")
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withInvalidValue() {
_, err := exp.NewInsertExpression(true)
iets.EqualError(err, "db: unsupported insert must be map, dbv2.Record, or struct type got: bool")
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withDifferentTypes() {
_, err := exp.NewInsertExpression(exp.Record{"a": "a1"}, true)
iets.EqualError(err, "db: rows must be all the same type expected exp.Record got bool")
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withNoValues() {
ie, err := exp.NewInsertExpression()
iets.NoError(err)
iets.Nil(ie.Cols())
iets.Nil(ie.Vals())
iets.True(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_Vals() {
ie, err := exp.NewInsertExpression()
iets.NoError(err)
vals := [][]interface{}{
{"a", "b"},
}
ie = ie.SetCols(exp.NewColumnListExpression("a", "b")).SetVals(vals)
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
iets.Equal(vals, ie.Vals())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_Cols() {
ie, err := exp.NewInsertExpression()
iets.NoError(err)
vals := [][]interface{}{
{"a", "b"},
}
ce := exp.NewColumnListExpression("a", "b")
ie = ie.SetCols(ce).SetVals(vals)
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
iets.Equal(vals, ie.Vals())
iets.Equal(ce, ie.Cols())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_From() {
ae := newTestAppendableExpression("select * from test", []interface{}{})
ie, err := exp.NewInsertExpression(ae)
iets.NoError(err)
iets.False(ie.IsEmpty())
iets.True(ie.IsInsertFrom())
iets.Equal(ae, ie.From())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_appendableExpression() {
ae := newTestAppendableExpression("test ae", nil)
ie, err := exp.NewInsertExpression(ae)
iets.NoError(err)
iets.False(ie.IsEmpty())
iets.True(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withRecords() {
ie, err := exp.NewInsertExpression(exp.Record{"c": "a"}, exp.Record{"c": "b"})
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("c"), ie.Cols())
iets.Equal([][]interface{}{{"a"}, {"b"}}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withRecordsSlice() {
ie, err := exp.NewInsertExpression([]exp.Record{{"c": "a"}, {"c": "b"}})
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("c"), ie.Cols())
iets.Equal([][]interface{}{{"a"}, {"b"}}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withRecordOfDifferentLength() {
_, err := exp.NewInsertExpression(exp.Record{"c": "a"}, exp.Record{"c": "b", "c2": "d"})
iets.EqualError(err, "db: rows with different value length expected 1 got 2")
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withRecordWithDifferentkeys() {
_, err := exp.NewInsertExpression(exp.Record{"c1": "a"}, exp.Record{"c2": "b"})
iets.EqualError(err, `db: rows with different keys expected ["c1"] got ["c2"]`)
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withMap() {
ie, err := exp.NewInsertExpression(
map[string]interface{}{"c": "a"},
map[string]interface{}{"c": "b"},
)
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("c"), ie.Cols())
iets.Equal([][]interface{}{{"a"}, {"b"}}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withStructs() {
type testRecord struct {
C string `db:"c"`
}
ie, err := exp.NewInsertExpression(
testRecord{C: "a"},
testRecord{C: "b"},
)
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("c"), ie.Cols())
iets.Equal([][]interface{}{{"a"}, {"b"}}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withStructSlice() {
type testRecord struct {
C string `db:"c"`
}
ie, err := exp.NewInsertExpression([]testRecord{
{C: "a"},
{C: "b"},
})
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("c"), ie.Cols())
iets.Equal([][]interface{}{{"a"}, {"b"}}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withStructsWithoutTags() {
type testRecord struct {
FieldA int64
FieldB bool
FieldC string
}
ie, err := exp.NewInsertExpression(
testRecord{FieldA: 1, FieldB: true, FieldC: "a"},
testRecord{FieldA: 2, FieldB: false, FieldC: "b"},
)
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("fielda", "fieldb", "fieldc"), ie.Cols())
iets.Equal([][]interface{}{{int64(1), true, "a"}, {int64(2), false, "b"}}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withStructsIgnoredDbTag() {
type testRecord struct {
FieldA int64 `db:"-"`
FieldB bool
FieldC string
}
ie, err := exp.NewInsertExpression(
testRecord{FieldA: 1, FieldB: true, FieldC: "a"},
testRecord{FieldA: 2, FieldB: false, FieldC: "b"},
)
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("fieldb", "fieldc"), ie.Cols())
iets.Equal([][]interface{}{{true, "a"}, {false, "b"}}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withStructsWithDbv2SkipInsert() {
type testRecord struct {
FieldA int64
FieldB bool `ff:"skipupdate"`
FieldC string `ff:"skipinsert"`
}
ie, err := exp.NewInsertExpression(
testRecord{FieldA: 1, FieldB: true, FieldC: "a"},
testRecord{FieldA: 2, FieldB: false, FieldC: "b"},
)
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("fielda", "fieldb"), ie.Cols())
iets.Equal([][]interface{}{{int64(1), true}, {int64(2), false}}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withStructPointers() {
type testRecord struct {
C string `db:"c"`
}
ie, err := exp.NewInsertExpression(
&testRecord{C: "a"},
&testRecord{C: "b"},
)
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("c"), ie.Cols())
iets.Equal([][]interface{}{{"a"}, {"b"}}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withStructsWithEmbeddedStructs() {
type Phone struct {
Primary string `db:"primary_phone"`
Home string `db:"home_phone"`
}
type item struct {
Phone
Address string `db:"address"`
Name string `db:"name"`
}
ie, err := exp.NewInsertExpression(
item{Address: "111 Test Addr", Name: "Test1", Phone: Phone{Home: "123123", Primary: "456456"}},
item{Address: "211 Test Addr", Name: "Test2", Phone: Phone{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", Phone: Phone{Home: "123123", Primary: "456456"}},
item{Address: "411 Test Addr", Name: "Test4", Phone: Phone{Home: "123123", Primary: "456456"}},
)
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("address", "home_phone", "name", "primary_phone"), ie.Cols())
iets.Equal([][]interface{}{
{"111 Test Addr", "123123", "Test1", "456456"},
{"211 Test Addr", "123123", "Test2", "456456"},
{"311 Test Addr", "123123", "Test3", "456456"},
{"411 Test Addr", "123123", "Test4", "456456"},
}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withStructsWithEmbeddedStructPointers() {
type Phone struct {
Primary string `db:"primary_phone"`
Home string `db:"home_phone"`
}
type item struct {
*Phone
Address string `db:"address"`
Name string `db:"name"`
}
ie, err := exp.NewInsertExpression(
item{Address: "111 Test Addr", Name: "Test1", Phone: &Phone{Home: "123123", Primary: "456456"}},
item{Address: "211 Test Addr", Name: "Test2", Phone: &Phone{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", Phone: &Phone{Home: "123123", Primary: "456456"}},
item{Address: "411 Test Addr", Name: "Test4", Phone: &Phone{Home: "123123", Primary: "456456"}},
)
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("address", "home_phone", "name", "primary_phone"), ie.Cols())
iets.Equal([][]interface{}{
{"111 Test Addr", "123123", "Test1", "456456"},
{"211 Test Addr", "123123", "Test2", "456456"},
{"311 Test Addr", "123123", "Test3", "456456"},
{"411 Test Addr", "123123", "Test4", "456456"},
}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withNilEmbeddedStructPointers() {
type Phone struct {
Primary string `db:"primary_phone"`
Home string `db:"home_phone"`
}
type item struct {
*Phone
Address string `db:"address"`
Name string `db:"name"`
}
ie, err := exp.NewInsertExpression(
item{Address: "111 Test Addr", Name: "Test1"},
item{Address: "211 Test Addr", Name: "Test2"},
item{Address: "311 Test Addr", Name: "Test3"},
item{Address: "411 Test Addr", Name: "Test4"},
)
iets.NoError(err)
iets.Equal(exp.NewColumnListExpression("address", "name"), ie.Cols())
iets.Equal([][]interface{}{
{"111 Test Addr", "Test1"},
{"211 Test Addr", "Test2"},
{"311 Test Addr", "Test3"},
{"411 Test Addr", "Test4"},
}, ie.Vals())
iets.False(ie.IsEmpty())
iets.False(ie.IsInsertFrom())
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withDifferentStructTypes() {
type Phone struct {
Primary string `db:"primary_phone"`
Home string `db:"home_phone"`
}
type item struct {
*Phone
Address string `db:"address"`
Name string `db:"name"`
}
_, err := exp.NewInsertExpression(
item{Address: "111 Test Addr", Name: "Test1"},
Phone{Home: "123123", Primary: "456456"},
item{Address: "311 Test Addr", Name: "Test3"},
Phone{Home: "123123", Primary: "456456"},
)
iets.EqualError(err, "db: rows must be all the same type expected exp_test.item got exp_test.Phone")
}
func (iets *insertExpressionTestSuite) TestNewInsertExpression_withDifferentColumnLengths() {
type Phone struct {
Primary string `db:"primary_phone"`
Home string `db:"home_phone"`
}
type Phone2 struct {
Primary string `db:"primary_phone2"`
Home string `db:"home_phone2"`
}
type item struct {
*Phone
*Phone2
Address string `db:"address"`
Name string `db:"name"`
}
_, err := exp.NewInsertExpression(
item{Address: "111 Test Addr", Name: "Test1", Phone2: &Phone2{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", Phone: &Phone{Home: "123123", Primary: "456456"}},
)
iets.EqualError(err, `db: rows with different keys expected `+
`["address","home_phone2","name","primary_phone2"] got ["address","home_phone","name","primary_phone"]`)
}
func TestInsertExpressionSuite(t *testing.T) {
suite.Run(t, new(insertExpressionTestSuite))
}