github.com/kunlun-qilian/sqlx/v3@v3.0.0/builder/expr_test.go (about) 1 package builder_test 2 3 import ( 4 "context" 5 "database/sql/driver" 6 "fmt" 7 "testing" 8 9 . "github.com/kunlun-qilian/sqlx/v3/builder" 10 . "github.com/kunlun-qilian/sqlx/v3/builder/buidertestingutils" 11 "github.com/onsi/gomega" 12 ) 13 14 func TestResolveExpr(t *testing.T) { 15 t.Run("empty", func(t *testing.T) { 16 gomega.NewWithT(t).Expect(ResolveExpr(nil)).To(gomega.BeNil()) 17 }) 18 } 19 20 type Byte uint8 21 22 func TestEx(t *testing.T) { 23 t.Run("empty query", func(t *testing.T) { 24 gomega.NewWithT(t).Expect( 25 Expr(""), 26 ).To(BeExpr("")) 27 }) 28 29 t.Run("flatten slice", func(t *testing.T) { 30 gomega.NewWithT(t).Expect( 31 Expr(`#ID IN (?)`, []int{28, 29, 30}), 32 ).To(BeExpr("#ID IN (?,?,?)", 28, 29, 30)) 33 }) 34 35 t.Run("flatten slice for slice with named byte", func(t *testing.T) { 36 gomega.NewWithT(t).Expect( 37 And( 38 And(nil, Col("f_id").In([]int{28})), 39 Col("f_id").In([]Byte{28}), 40 ), 41 ).To(BeExpr("((f_id IN (?))) AND (f_id IN (?))", 28, Byte(28))) 42 }) 43 44 t.Run("flatten should skip for bytes", func(t *testing.T) { 45 gomega.NewWithT(t).Expect( 46 Expr(`#ID = (?)`, []byte("")), 47 ).To(BeExpr("#ID = (?)", []byte(""))) 48 }) 49 50 t.Run("flatten with sub expr ", func(t *testing.T) { 51 gomega.NewWithT(t).Expect( 52 Expr(`#ID = ?`, Expr("#ID + ?", 1)), 53 ).To(BeExpr("#ID = #ID + ?", 1)) 54 }) 55 56 t.Run("flatten with ValuerExpr", func(t *testing.T) { 57 gomega.NewWithT(t).Expect( 58 Expr(`#Point = ?`, Point{1, 1}), 59 ).To(BeExpr("#Point = ST_GeomFromText(?)", Point{1, 1})) 60 }) 61 } 62 63 func BenchmarkEx(b *testing.B) { 64 b.Run("empty query", func(b *testing.B) { 65 for i := 0; i < b.N; i++ { 66 _ = Expr("").Ex(context.Background()) 67 } 68 }) 69 70 b.Run("flatten slice", func(b *testing.B) { 71 for i := 0; i < b.N; i++ { 72 Expr(`#ID IN (?)`, []int{28, 29, 30}).Ex(context.Background()) 73 } 74 }) 75 76 b.Run("flatten with sub expr", func(b *testing.B) { 77 b.Run("raw", func(b *testing.B) { 78 eb := Expr("") 79 eb.Grow(2) 80 81 eb.WriteQuery("#ID > ?") 82 eb.WriteQuery(" AND ") 83 eb.WriteQuery("#ID < ?") 84 85 eb.AppendArgs(1, 10) 86 87 rawBuild := func() *Ex { 88 return eb.Ex(context.Background()) 89 } 90 91 clone := func(ex *Ex) *Ex { 92 return Expr(ex.Query(), ex.Args()...).Ex(context.Background()) 93 } 94 95 b.Run("clone", func(b *testing.B) { 96 ex := rawBuild() 97 98 for i := 0; i < b.N; i++ { 99 _ = clone(ex) 100 } 101 }) 102 }) 103 104 b.Run("IsNilExpr", func(b *testing.B) { 105 for i := 0; i < b.N; i++ { 106 IsNilExpr(Expr(`#ID > ?`, 1)) 107 } 108 }) 109 110 b.Run("by chain", func(b *testing.B) { 111 for i := 0; i < b.N; i++ { 112 e := AsCond(Expr(`#ID > ?`, 1)).And(AsCond(Expr(`#ID < ?`, 10))) 113 e.Ex(context.Background()) 114 } 115 }) 116 117 b.Run("by expr", func(b *testing.B) { 118 for i := 0; i < b.N; i++ { 119 e := And( 120 Col("f_id").Lt(0), 121 Col("f_id").In([]int{1, 2, 3}), 122 ) 123 e.Ex(context.Background()) 124 } 125 }) 126 127 b.Run("by expr without re created", func(b *testing.B) { 128 left := Col("f_id").Lt(0) 129 right := Col("f_id").In([]int{1, 2, 3}) 130 131 b.Run("single", func(b *testing.B) { 132 for i := 0; i < b.N; i++ { 133 left.Ex(context.Background()) 134 } 135 }) 136 137 b.Run("composed", func(b *testing.B) { 138 e := And(left, left, right, right) 139 140 b.Log(e.Ex(context.Background()).Query()) 141 142 for i := 0; i < b.N; i++ { 143 e.Ex(context.Background()) 144 } 145 }) 146 }) 147 }) 148 } 149 150 type Point struct { 151 X float64 152 Y float64 153 } 154 155 func (Point) DataType(engine string) string { 156 return "POINT" 157 } 158 159 func (Point) ValueEx() string { 160 return `ST_GeomFromText(?)` 161 } 162 163 func (p Point) Value() (driver.Value, error) { 164 return fmt.Sprintf("POINT(%v %v)", p.X, p.Y), nil 165 }