1package norm
2
3import (
4 _ "github.com/mattn/go-sqlite3"
5 "testing"
6)
7
8func TestSelectCompileSuccess(t *testing.T) {
9 tests := []struct {
10 name string
11 stmt Compiler
12 expectedSql string
13 expectedArgs []any
14 }{
15 {
16 name: "Simple select",
17 stmt: Select("name", "age").From("users"),
18 expectedSql: "SELECT name, age FROM users",
19 expectedArgs: nil,
20 },
21 {
22 name: "Select with where",
23 stmt: Select("*").
24 From("users").
25 Where(Eq("active", true)),
26 expectedSql: "SELECT * FROM users WHERE (active) = (?)",
27 expectedArgs: []any{true},
28 },
29 {
30 name: "Select with order by",
31 stmt: Select("name").
32 From("users").
33 OrderBy("name", Ascending),
34 expectedSql: "SELECT name FROM users ORDER BY name asc",
35 expectedArgs: nil,
36 },
37 {
38 name: "Select with multiple order by",
39 stmt: Select("name", "age").
40 From("users").
41 OrderBy("name", Ascending).
42 OrderBy("age", Descending),
43 expectedSql: "SELECT name, age FROM users ORDER BY name asc, age desc",
44 expectedArgs: nil,
45 },
46 {
47 name: "Select with group by",
48 stmt: Select("department", "COUNT(*)").
49 From("users").
50 GroupBy("department"),
51 expectedSql: "SELECT department, COUNT(*) FROM users GROUP BY department",
52 expectedArgs: nil,
53 },
54 {
55 name: "Select with limit",
56 stmt: Select("*").
57 From("users").
58 Limit(5),
59 expectedSql: "SELECT * FROM users LIMIT 5",
60 expectedArgs: nil,
61 },
62 {
63 name: "Complex select",
64 stmt: Select("name", "age", "department").
65 From("users").
66 Where(Eq("active", true).And(Gt("age", 18))).
67 GroupBy("department").
68 OrderBy("name", Ascending).
69 Limit(10),
70 expectedSql: "SELECT name, age, department FROM users WHERE ((active) = (?)) AND ((age) > (?)) GROUP BY department ORDER BY name asc LIMIT 10",
71 expectedArgs: []any{true, 18},
72 },
73 }
74
75 for _, test := range tests {
76 t.Run(test.name, func(t *testing.T) {
77 sql, args := test.stmt.MustCompile()
78
79 if sql != test.expectedSql {
80 t.Errorf("Expected '%s', got '%s'", test.expectedSql, sql)
81 }
82
83 if len(args) != len(test.expectedArgs) {
84 t.Errorf("Expected '%d' args, got '%d' args", len(test.expectedArgs), len(args))
85 }
86
87 for i := range len(args) {
88 if args[i] != test.expectedArgs[i] {
89 t.Errorf("Expected '%s', got '%s' at index %d", test.expectedArgs[i], args[i], i)
90 }
91 }
92 })
93 }
94}
95
96func TestSelectCompileFail(t *testing.T) {
97 tests := []struct {
98 name string
99 stmt Compiler
100 expectedError string
101 }{
102 {
103 name: "No columns",
104 stmt: Select(),
105 expectedError: "result columns empty",
106 },
107 {
108 name: "No from clause",
109 stmt: Select("name"),
110 expectedError: "FROM clause is required",
111 },
112 {
113 name: "Invalid limit",
114 stmt: Select("name").
115 From("users").
116 Limit(0),
117 expectedError: "LIMIT must be positive, got 0",
118 },
119 {
120 name: "Negative limit",
121 stmt: Select("name").
122 From("users").
123 Limit(-5),
124 expectedError: "LIMIT must be positive, got -5",
125 },
126 }
127
128 for _, test := range tests {
129 t.Run(test.name, func(t *testing.T) {
130 sql, args, err := test.stmt.Compile()
131
132 if err == nil {
133 t.Error("Expected error, got nil")
134 }
135
136 if err.Error() != test.expectedError {
137 t.Errorf("Expected error '%s', got '%s'", test.expectedError, err.Error())
138 }
139
140 if sql != "" {
141 t.Errorf("Expected empty SQL on error, got '%s'", sql)
142 }
143
144 if args != nil {
145 t.Errorf("Expected empty args on error, got '%q'", args)
146 }
147 })
148 }
149}
150
151func TestSelectIntegration(t *testing.T) {
152 db := setupTestDB(t)
153 defer db.Close()
154
155 tests := []struct {
156 name string
157 stmt select_
158 expectedRows int
159 }{
160 {
161 name: "Select all users",
162 stmt: Select("*").From("users"),
163 expectedRows: 6,
164 },
165 {
166 name: "Select active users only",
167 stmt: Select("name", "email").
168 From("users").
169 Where(Eq("active", true)),
170 expectedRows: 4,
171 },
172 {
173 name: "Select users in Engineering",
174 stmt: Select("name", "age").
175 From("users").
176 Where(Eq("department", "Engineering")),
177 expectedRows: 3,
178 },
179 {
180 name: "Select users with age > 30",
181 stmt: Select("name", "age").
182 From("users").
183 Where(Gt("age", 30)),
184 expectedRows: 2,
185 },
186 {
187 name: "Select users with salary between 70000 AND 80000",
188 stmt: Select("name", "salary").
189 From("users").
190 Where(Gte("salary", 70000.0).And(Lte("salary", 80000.0))),
191 expectedRows: 3,
192 },
193 }
194
195 for _, test := range tests {
196 t.Run(test.name, func(t *testing.T) {
197 rows, err := test.stmt.Query(db)
198 if err != nil {
199 t.Fatalf("Failed to build query: %v", err)
200 }
201
202 count := 0
203 for rows.Next() {
204 count++
205 }
206
207 if count != test.expectedRows {
208 t.Errorf("Expected %d rows, got %d", test.expectedRows, count)
209 }
210 })
211 }
212}