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>
384 lines
12 KiB
Go
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))
|
|
}
|