package duckdb_test import ( "testing" dbv2 "git.fsdpf.net/go/db" "git.fsdpf.net/go/db/dialect/duckdb" "github.com/stretchr/testify/assert" ) func TestDialectOptions(t *testing.T) { opts := duckdb.DialectOptions() assert.NotNil(t, opts) assert.Equal(t, '"', opts.QuoteRune) assert.True(t, opts.IncludePlaceholderNum) assert.Equal(t, []byte("$"), opts.PlaceHolderFragment) assert.True(t, opts.SupportsReturn) assert.True(t, opts.SupportsConflictTarget) assert.True(t, opts.SupportsWithCTE) assert.True(t, opts.SupportsDistinctOn) assert.True(t, opts.SupportsWindowFunction) } func TestDialectRegistration(t *testing.T) { // Verify the dialect is registered dialect := dbv2.GetDialect("duckdb") assert.NotNil(t, dialect) } func TestSelectSQL(t *testing.T) { db := dbv2.Dialect("duckdb") ds := db.From("users") sql, _, err := ds.ToSQL() assert.NoError(t, err) assert.Equal(t, `SELECT * FROM "users"`, sql) ds = db.From("users").Select("id", "name") sql, _, err = ds.ToSQL() assert.NoError(t, err) assert.Equal(t, `SELECT "id", "name" FROM "users"`, sql) ds = db.From("users").Where(dbv2.C("id").Eq(1)) sql, _, err = ds.ToSQL() assert.NoError(t, err) assert.Equal(t, `SELECT * FROM "users" WHERE ("id" = 1)`, sql) } func TestPreparedStatement(t *testing.T) { db := dbv2.Dialect("duckdb") ds := db.From("users").Prepared(true).Where(dbv2.C("id").Eq(1)) sql, args, err := ds.ToSQL() assert.NoError(t, err) assert.Equal(t, `SELECT * FROM "users" WHERE ("id" = $1)`, sql) assert.Equal(t, []interface{}{int64(1)}, args) ds = db.From("users").Prepared(true).Where(dbv2.C("name").Eq("John")) sql, args, err = ds.ToSQL() assert.NoError(t, err) assert.Equal(t, `SELECT * FROM "users" WHERE ("name" = $1)`, sql) assert.Equal(t, []interface{}{"John"}, args) } func TestInsertSQL(t *testing.T) { db := dbv2.Dialect("duckdb") ds := db.Insert("users").Rows(dbv2.Record{"id": 1, "name": "John"}) sql, _, err := ds.ToSQL() assert.NoError(t, err) assert.Contains(t, sql, `INSERT INTO "users"`) assert.Contains(t, sql, `"id"`) assert.Contains(t, sql, `"name"`) } func TestUpdateSQL(t *testing.T) { db := dbv2.Dialect("duckdb") ds := db.Update("users").Set(dbv2.Record{"name": "Jane"}).Where(dbv2.C("id").Eq(1)) sql, _, err := ds.ToSQL() assert.NoError(t, err) assert.Contains(t, sql, `UPDATE "users"`) assert.Contains(t, sql, `"name"`) assert.Contains(t, sql, `WHERE ("id" = 1)`) } func TestDeleteSQL(t *testing.T) { db := dbv2.Dialect("duckdb") ds := db.Delete("users").Where(dbv2.C("id").Eq(1)) sql, _, err := ds.ToSQL() assert.NoError(t, err) assert.Equal(t, `DELETE FROM "users" WHERE ("id" = 1)`, sql) } func TestJoinSQL(t *testing.T) { db := dbv2.Dialect("duckdb") ds := db.From("users"). Join(dbv2.T("orders"), dbv2.On(dbv2.Ex{"users.id": dbv2.I("orders.user_id")})). Select("users.name", "orders.total") sql, _, err := ds.ToSQL() assert.NoError(t, err) assert.Contains(t, sql, `FROM "users"`) assert.Contains(t, sql, `INNER JOIN "orders"`) assert.Contains(t, sql, `ON ("users"."id" = "orders"."user_id")`) } func TestRegexpSQL(t *testing.T) { db := dbv2.Dialect("duckdb") // RegexpLike → regexp_matches(col, pattern) ds := db.From("docs").Where(dbv2.C("content").RegexpLike("简介")) sql, _, err := ds.ToSQL() assert.NoError(t, err) assert.Equal(t, `SELECT * FROM "docs" WHERE regexp_matches("content", '简介')`, sql) // RegexpILike → 同样生成 regexp_matches ds = db.From("docs").Where(dbv2.C("content").RegexpILike("简介")) sql, _, err = ds.ToSQL() assert.NoError(t, err) assert.Equal(t, `SELECT * FROM "docs" WHERE regexp_matches("content", '简介')`, sql) } func TestRegexpPreparedSQL(t *testing.T) { db := dbv2.Dialect("duckdb") ds := db.From("docs").Prepared(true).Where(dbv2.C("content").RegexpLike("简介")) sql, args, err := ds.ToSQL() assert.NoError(t, err) assert.Equal(t, `SELECT * FROM "docs" WHERE regexp_matches("content", $1)`, sql) assert.Equal(t, []interface{}{"简介"}, args) } func TestWindowFunction(t *testing.T) { db := dbv2.Dialect("duckdb") ds := db.From("sales"). Select( "product", "amount", dbv2.ROW_NUMBER().Over(dbv2.W().PartitionBy("product").OrderBy(dbv2.C("amount").Desc())).As("rank"), ) sql, _, err := ds.ToSQL() assert.NoError(t, err) assert.Contains(t, sql, `ROW_NUMBER()`) assert.Contains(t, sql, `OVER`) assert.Contains(t, sql, `PARTITION BY`) } func TestCTE(t *testing.T) { db := dbv2.Dialect("duckdb") cte := db.From("users").Where(dbv2.C("active").IsTrue()) ds := db.From("active_users").With("active_users", cte).Select("*") sql, _, err := ds.ToSQL() assert.NoError(t, err) assert.Contains(t, sql, `WITH active_users AS`) assert.Contains(t, sql, `SELECT * FROM "users" WHERE ("active" IS TRUE)`) }