Skip to content

Commit e95bd9f

Browse files
committed
Extend tests
1 parent 76ba19c commit e95bd9f

4 files changed

Lines changed: 299 additions & 6 deletions

File tree

db_test.go

Lines changed: 299 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,46 @@ limitations under the License.
1717
package sequel
1818

1919
import (
20+
"encoding/json"
2021
"testing"
22+
"time"
2123

2224
"github.com/microbus-io/sequel/testdata"
2325
"github.com/microbus-io/testarossa"
2426
)
2527

2628
func TestDB_AutoCreate(t *testing.T) {
27-
for _, driver := range []string{"mysql", "pgx" /* , "mssql" */} {
28-
t.Run(driver, func(t *testing.T) {
29+
t.Parallel()
30+
dsns := map[string]string{
31+
"mysql": "root:root@tcp(127.0.0.1:3306)/",
32+
"pgx": "postgres://postgres:postgres@127.0.0.1:5432/",
33+
// "mssql": "sqlserver://sa:Password123@127.0.0.1:1433",
34+
}
35+
for drv, dsn := range dsns {
36+
t.Run(drv, func(t *testing.T) {
2937
assert := testarossa.For(t)
3038

31-
db, err := OpenTesting(driver, "", "AutoCreate")
39+
db, err := OpenTesting(drv, dsn, t.Name())
3240
assert.NoError(err)
33-
assert.NotNil(db)
41+
if !assert.NotNil(db) {
42+
return
43+
}
3444
defer db.Close()
3545

3646
err = db.Migrate("auto_create", testdata.FS)
3747
assert.NoError(err)
3848

39-
row := db.QueryRow("SELECT COUNT(id) FROM foo")
4049
var count int
41-
err = row.Scan(&count)
50+
stmt := "SELECT COUNT(id) FROM foo"
51+
err = db.QueryRow(stmt).Scan(&count)
4252
assert.NoError(err)
4353
assert.Equal(3, count)
54+
55+
var id int
56+
stmt = db.ConformArgPlaceholders("SELECT id FROM foo WHERE id=?")
57+
err = db.QueryRow(stmt, 1).Scan(&id)
58+
assert.NoError(err)
59+
assert.Equal(1, id)
4460
})
4561
}
4662
}
@@ -86,4 +102,281 @@ func TestDB_DatabaseNameFromDataSourceName(t *testing.T) {
86102
assert.Expect(name, "my_database", err, nil)
87103
name, err = databaseNameFromDataSourceName("mssql", "sqlserver://user:pw@127.0.0.1:1433")
88104
assert.Expect(name, "", err, nil)
105+
106+
// empty dsn
107+
_, err = databaseNameFromDataSourceName("mysql", "")
108+
assert.Error(err)
109+
110+
// unsupported driver
111+
_, err = databaseNameFromDataSourceName("sqlite", "file.db")
112+
assert.Error(err)
113+
}
114+
115+
func TestDB_InferDriverName(t *testing.T) {
116+
t.Parallel()
117+
assert := testarossa.For(t)
118+
119+
// Postgres prefix
120+
assert.Equal("pgx", inferDriverName("postgres://user:pw@127.0.0.1:5432/mydb"))
121+
122+
// SQL Server prefix
123+
assert.Equal("mssql", inferDriverName("sqlserver://user:pw@127.0.0.1:1433"))
124+
125+
// MySQL tcp() style
126+
assert.Equal("mysql", inferDriverName("root:root@tcp(127.0.0.1:3306)/"))
127+
128+
// Port-based inference
129+
assert.Equal("mysql", inferDriverName("root:root@127.0.0.1:3306/"))
130+
assert.Equal("pgx", inferDriverName("user:pw@127.0.0.1:5432/"))
131+
assert.Equal("mssql", inferDriverName("user:pw@127.0.0.1:1433"))
132+
133+
// Empty string
134+
assert.Equal("", inferDriverName(""))
135+
136+
// Unrecognizable DSN
137+
assert.Equal("", inferDriverName("some-unknown-dsn"))
138+
}
139+
140+
func TestDB_SetDatabaseInDataSourceName(t *testing.T) {
141+
t.Parallel()
142+
assert := testarossa.For(t)
143+
144+
// mysql - set database
145+
dsn, err := setDatabaseInDataSourceName("mysql", "root:root@tcp(127.0.0.1:3306)/", "mydb")
146+
assert.NoError(err)
147+
name, _ := databaseNameFromDataSourceName("mysql", dsn)
148+
assert.Equal("mydb", name)
149+
150+
// mysql - clear database
151+
dsn, err = setDatabaseInDataSourceName("mysql", "root:root@tcp(127.0.0.1:3306)/mydb", "")
152+
assert.NoError(err)
153+
name, _ = databaseNameFromDataSourceName("mysql", dsn)
154+
assert.Equal("", name)
155+
156+
// pgx - set database
157+
dsn, err = setDatabaseInDataSourceName("pgx", "postgres://user:pw@127.0.0.1:5432/", "mydb")
158+
assert.NoError(err)
159+
name, _ = databaseNameFromDataSourceName("pgx", dsn)
160+
assert.Equal("mydb", name)
161+
162+
// pgx - clear database
163+
dsn, err = setDatabaseInDataSourceName("pgx", "postgres://user:pw@127.0.0.1:5432/mydb", "")
164+
assert.NoError(err)
165+
name, _ = databaseNameFromDataSourceName("pgx", dsn)
166+
assert.Equal("", name)
167+
168+
// mssql - set database
169+
dsn, err = setDatabaseInDataSourceName("mssql", "sqlserver://user:pw@127.0.0.1:1433", "mydb")
170+
assert.NoError(err)
171+
name, _ = databaseNameFromDataSourceName("mssql", dsn)
172+
assert.Equal("mydb", name)
173+
174+
// mssql - clear database
175+
dsn, err = setDatabaseInDataSourceName("mssql", "sqlserver://user:pw@127.0.0.1:1433?database=mydb", "")
176+
assert.NoError(err)
177+
name, _ = databaseNameFromDataSourceName("mssql", dsn)
178+
assert.Equal("", name)
179+
180+
// empty dsn
181+
_, err = setDatabaseInDataSourceName("mysql", "", "mydb")
182+
assert.Error(err)
183+
184+
// unsupported driver
185+
_, err = setDatabaseInDataSourceName("sqlite", "file.db", "mydb")
186+
assert.Error(err)
187+
}
188+
189+
func TestDB_ConformArgPlaceholders_NoArgs(t *testing.T) {
190+
t.Parallel()
191+
assert := testarossa.For(t)
192+
193+
db := &DB{driverName: "pgx"}
194+
stmt := `SELECT * FROM foo WHERE id=1`
195+
assert.Equal(stmt, db.ConformArgPlaceholders(stmt))
196+
}
197+
198+
func TestDB_ConformArgPlaceholders_NonPgx(t *testing.T) {
199+
t.Parallel()
200+
assert := testarossa.For(t)
201+
202+
// MySQL driver should return the statement unchanged
203+
db := &DB{driverName: "mysql"}
204+
stmt := `SELECT * FROM foo WHERE id=? AND name=?`
205+
assert.Equal(stmt, db.ConformArgPlaceholders(stmt))
206+
207+
// MSSQL driver should also return unchanged
208+
db = &DB{driverName: "mssql"}
209+
assert.Equal(stmt, db.ConformArgPlaceholders(stmt))
210+
}
211+
212+
func TestDB_NowUTC(t *testing.T) {
213+
t.Parallel()
214+
assert := testarossa.For(t)
215+
216+
db := &DB{driverName: "mysql"}
217+
assert.Equal("UTC_TIMESTAMP(3)", db.NowUTC())
218+
219+
db = &DB{driverName: "pgx"}
220+
assert.Equal("(NOW() AT TIME ZONE 'UTC')", db.NowUTC())
221+
222+
db = &DB{driverName: "mssql"}
223+
assert.Equal("SYSUTCDATETIME()", db.NowUTC())
224+
225+
db = &DB{driverName: "unknown"}
226+
assert.Equal("", db.NowUTC())
227+
}
228+
229+
func TestDB_RegexpTextSearch(t *testing.T) {
230+
t.Parallel()
231+
assert := testarossa.For(t)
232+
233+
// MySQL
234+
db := &DB{driverName: "mysql"}
235+
assert.Equal("''"+` REGEXP ?`, db.RegexpTextSearch())
236+
assert.Equal("name REGEXP ?", db.RegexpTextSearch("name"))
237+
assert.Equal("CONCAT_WS(' ',name,email) REGEXP ?", db.RegexpTextSearch("name", "email"))
238+
239+
// Postgres
240+
db = &DB{driverName: "pgx"}
241+
assert.Equal("REGEXP_LIKE('', ?, 'i')", db.RegexpTextSearch())
242+
assert.Equal("REGEXP_LIKE(name, ?, 'i')", db.RegexpTextSearch("name"))
243+
assert.Equal("REGEXP_LIKE(CONCAT_WS(' ',name,email), ?, 'i')", db.RegexpTextSearch("name", "email"))
244+
245+
// MSSQL
246+
db = &DB{driverName: "mssql"}
247+
assert.Equal("REGEXP_LIKE('', ?, 'i')", db.RegexpTextSearch())
248+
assert.Equal("REGEXP_LIKE(name, ?, 'i')", db.RegexpTextSearch("name"))
249+
250+
// Unknown driver
251+
db = &DB{driverName: "unknown"}
252+
assert.Equal("", db.RegexpTextSearch("name"))
253+
}
254+
255+
func TestDB_Nullify(t *testing.T) {
256+
t.Parallel()
257+
assert := testarossa.For(t)
258+
259+
// Zero values should return nil
260+
assert.Nil(Nullify(""))
261+
assert.Nil(Nullify(0))
262+
assert.Nil(Nullify(false))
263+
assert.Nil(Nullify(time.Time{}))
264+
265+
// Non-zero values should return the value itself
266+
assert.Equal("hello", Nullify("hello"))
267+
assert.Equal(42, Nullify(42))
268+
assert.Equal(true, Nullify(true))
269+
now := time.Now()
270+
assert.Equal(now, Nullify(now))
271+
}
272+
273+
func TestDB_Nullable(t *testing.T) {
274+
t.Parallel()
275+
assert := testarossa.For(t)
276+
277+
var s string
278+
n := Nullable(&s)
279+
280+
// Simulate scanning a value
281+
n.V = "hello"
282+
n.Valid = true
283+
err := ApplyBindings(n)
284+
assert.NoError(err)
285+
assert.Equal("hello", s)
286+
287+
// Simulate scanning a NULL (Valid=false, V is zero)
288+
s = "previous"
289+
n2 := Nullable(&s)
290+
n2.Valid = false
291+
err = ApplyBindings(n2)
292+
assert.NoError(err)
293+
assert.Equal("", s)
294+
}
295+
296+
func TestDB_Bind(t *testing.T) {
297+
t.Parallel()
298+
assert := testarossa.For(t)
299+
300+
var tags []string
301+
b := Bind(func(value string) error {
302+
return json.Unmarshal([]byte(value), &tags)
303+
})
304+
305+
// Simulate scanning a JSON string
306+
b.V = `["a","b","c"]`
307+
b.Valid = true
308+
err := ApplyBindings(b)
309+
assert.NoError(err)
310+
assert.Len(tags, 3)
311+
assert.Equal("a", tags[0])
312+
assert.Equal("b", tags[1])
313+
assert.Equal("c", tags[2])
314+
}
315+
316+
func TestDB_Bind_Error(t *testing.T) {
317+
t.Parallel()
318+
assert := testarossa.For(t)
319+
320+
b := Bind(func(value string) error {
321+
return json.Unmarshal([]byte(value), &[]int{})
322+
})
323+
324+
// Simulate scanning invalid JSON
325+
b.V = `not-json`
326+
b.Valid = true
327+
err := ApplyBindings(b)
328+
assert.Error(err)
329+
}
330+
331+
func TestDB_ApplyBindings_NoBindings(t *testing.T) {
332+
t.Parallel()
333+
assert := testarossa.For(t)
334+
335+
// ApplyBindings should be safe with non-binder args
336+
var x int
337+
var s string
338+
err := ApplyBindings(&x, &s)
339+
assert.NoError(err)
340+
341+
// Empty args
342+
err = ApplyBindings()
343+
assert.NoError(err)
344+
}
345+
346+
func TestDB_DriverName(t *testing.T) {
347+
t.Parallel()
348+
assert := testarossa.For(t)
349+
350+
db := &DB{driverName: "mysql"}
351+
assert.Equal("mysql", db.DriverName())
352+
353+
db = &DB{driverName: "pgx"}
354+
assert.Equal("pgx", db.DriverName())
355+
}
356+
357+
func TestDB_CloseNil(t *testing.T) {
358+
t.Parallel()
359+
assert := testarossa.For(t)
360+
361+
// Close on nil DB should not panic
362+
var db *DB
363+
err := db.Close()
364+
assert.NoError(err)
365+
}
366+
367+
func TestDB_OpenEmptyDSN(t *testing.T) {
368+
t.Parallel()
369+
assert := testarossa.For(t)
370+
371+
_, err := Open("mysql", "")
372+
assert.Error(err)
373+
}
374+
375+
func TestDB_OpenInferDriverFails(t *testing.T) {
376+
t.Parallel()
377+
assert := testarossa.For(t)
378+
379+
// Unrecognizable DSN without explicit driver
380+
_, err := Open("", "some-unknown-connection-string")
381+
assert.Error(err)
89382
}

0 commit comments

Comments
 (0)