From ddb52355786e2ff37039aba3d5137f624d2a3f8f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 08:49:32 +0000 Subject: [PATCH 1/6] Initial plan From c50fdf41453a91955f59ba7145a7c45f2ac087fc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 08:55:01 +0000 Subject: [PATCH 2/6] Add support for disabling slow query logging Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com> --- README.md | 52 +++++++++++++++++++++ adapter.go | 121 +++++++++++++++++++++++++++++++++++++++++++----- adapter_test.go | 64 +++++++++++++++++++++++++ 3 files changed, 226 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ff2b04f..91b9546 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,58 @@ TurnOffAutoMigrate(db) a,_ := NewAdapterByDBWithCustomTable(...) ``` Find out more details at [gorm-adapter#162](https://github.com/casbin/gorm-adapter/issues/162) + +## Disable Slow Query Logging + +By default, GORM logs slow queries (queries taking more than 200ms). To disable this logging, you can use `NewAdapterWithConfig` with a custom logger configuration: + +```go +package main + +import ( + "github.com/casbin/casbin/v2" + gormadapter "github.com/casbin/gorm-adapter/v3" +) + +func main() { + // Create a config without slow query logging + config := gormadapter.NewConfigWithoutSlowQueryLog() + + // Initialize adapter with the config + a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config) + e, _ := casbin.NewEnforcer("examples/rbac_model.conf", a) + + // Load the policy from DB - no slow query logs will be printed + e.LoadPolicy() + + // Check the permission + e.Enforce("alice", "data1", "read") +} +``` + +You can also use `NewAdapterWithConfig` with database name and table name parameters, just like `NewAdapter`: + +```go +config := gormadapter.NewConfigWithoutSlowQueryLog() +// With database name +a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config, "casbin") +// With database name and table name +a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config, "casbin", "casbin_rule") +``` + +If you need more control over the logger, you can also create a custom `gorm.Config`: + +```go +import "gorm.io/gorm/logger" + +config := &gorm.Config{ + Logger: logger.Default.LogMode(logger.Silent), // Completely silent + // Or use logger.Error to only show errors: + // Logger: logger.Default.LogMode(logger.Error), +} +a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config) +``` + ## Customize table columns example You can change the gorm struct tags, but the table structure must stay the same. ```go diff --git a/adapter.go b/adapter.go index ae5c6af..8003dc6 100755 --- a/adapter.go +++ b/adapter.go @@ -86,6 +86,7 @@ type Adapter struct { isFiltered bool transactionMu *sync.Mutex muInitialize sync.Once + gormConfig *gorm.Config } // finalizer is the destructor for Adapter. @@ -193,6 +194,82 @@ func NewAdapter(driverName string, dataSourceName string, params ...interface{}) return a, nil } +// NewAdapterWithConfig is the constructor for Adapter with custom gorm.Config. +// This allows you to customize GORM behavior, including disabling slow query logging. +// Params are the same as NewAdapter, with an additional config parameter. +// +// Example usage to disable slow query logging: +// +// config := gormadapter.NewConfigWithoutSlowQueryLog() +// a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config) +// +// Or with database name: +// +// config := gormadapter.NewConfigWithoutSlowQueryLog() +// a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config, "casbin") +func NewAdapterWithConfig(driverName string, dataSourceName string, config *gorm.Config, params ...interface{}) (*Adapter, error) { + a := &Adapter{} + a.driverName = driverName + a.dataSourceName = dataSourceName + a.gormConfig = config + + a.tableName = defaultTableName + a.databaseName = defaultDatabaseName + a.dbSpecified = false + a.transactionMu = &sync.Mutex{} + + if len(params) == 1 { + switch p1 := params[0].(type) { + case bool: + a.dbSpecified = p1 + case string: + a.databaseName = p1 + default: + return nil, errors.New("wrong format") + } + } else if len(params) == 2 { + switch p2 := params[1].(type) { + case bool: + a.dbSpecified = p2 + p1, ok := params[0].(string) + if !ok { + return nil, errors.New("wrong format") + } + a.databaseName = p1 + case string: + p1, ok := params[0].(string) + if !ok { + return nil, errors.New("wrong format") + } + a.databaseName = p1 + a.tableName = p2 + default: + return nil, errors.New("wrong format") + } + } else if len(params) == 3 { + if p3, ok := params[2].(bool); ok { + a.dbSpecified = p3 + a.databaseName = params[0].(string) + a.tableName = params[1].(string) + } else { + return nil, errors.New("wrong format") + } + } else if len(params) != 0 { + return nil, errors.New("too many parameters") + } + + // Open the DB, create it if not existed. + err := a.Open() + if err != nil { + return nil, err + } + + // Call the destructor when the object is released. + runtime.SetFinalizer(a, finalizer) + + return a, nil +} + // NewAdapterByDBUseTableName creates gorm-adapter by an existing Gorm instance and the specified table prefix and table name // Example: gormadapter.NewAdapterByDBUseTableName(&db, "cms", "casbin") Automatically generate table name like this "cms_casbin" func NewAdapterByDBUseTableName(db *gorm.DB, prefix string, tableName string) (*Adapter, error) { @@ -315,17 +392,39 @@ func NewAdapterByDBWithCustomTable(db *gorm.DB, t interface{}, tableName ...stri return NewAdapterByDBUseTableName(db.WithContext(ctx), "", curTableName) } -func openDBConnection(driverName, dataSourceName string) (*gorm.DB, error) { +// NewConfigWithoutSlowQueryLog creates a gorm.Config with slow query logging disabled. +// This can be used to suppress GORM's slow SQL log output. +// +// Example usage: +// +// config := gormadapter.NewConfigWithoutSlowQueryLog() +// a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config) +func NewConfigWithoutSlowQueryLog() *gorm.Config { + return &gorm.Config{ + Logger: logger.Default.LogMode(logger.Silent), + } +} + +func openDBConnection(driverName, dataSourceName string, config ...*gorm.Config) (*gorm.DB, error) { var err error var db *gorm.DB + + // Use provided config or default + var cfg *gorm.Config + if len(config) > 0 && config[0] != nil { + cfg = config[0] + } else { + cfg = &gorm.Config{} + } + if driverName == "postgres" { - db, err = gorm.Open(postgres.Open(dataSourceName), &gorm.Config{}) + db, err = gorm.Open(postgres.Open(dataSourceName), cfg) } else if driverName == "mysql" { - db, err = gorm.Open(mysql.Open(dataSourceName), &gorm.Config{}) + db, err = gorm.Open(mysql.Open(dataSourceName), cfg) } else if driverName == "sqlserver" { - db, err = gorm.Open(sqlserver.Open(dataSourceName), &gorm.Config{}) + db, err = gorm.Open(sqlserver.Open(dataSourceName), cfg) } else if driverName == "sqlite3" { - db, err = gorm.Open(sqlite.Open(dataSourceName), &gorm.Config{}) + db, err = gorm.Open(sqlite.Open(dataSourceName), cfg) } else { return nil, errors.New("Database dialect '" + driverName + "' is not supported. Supported databases are postgres, mysql, sqlserver and sqlite3") } @@ -337,7 +436,7 @@ func openDBConnection(driverName, dataSourceName string) (*gorm.DB, error) { func (a *Adapter) createDatabase() error { var err error - db, err := openDBConnection(a.driverName, a.dataSourceName) + db, err := openDBConnection(a.driverName, a.dataSourceName, a.gormConfig) if err != nil { return err } @@ -362,7 +461,7 @@ func (a *Adapter) Open() error { var db *gorm.DB if a.dbSpecified { - db, err = openDBConnection(a.driverName, a.dataSourceName) + db, err = openDBConnection(a.driverName, a.dataSourceName, a.gormConfig) if err != nil { return err } @@ -371,13 +470,13 @@ func (a *Adapter) Open() error { return err } if a.driverName == "postgres" { - db, err = openDBConnection(a.driverName, a.dataSourceName+" dbname="+a.databaseName) + db, err = openDBConnection(a.driverName, a.dataSourceName+" dbname="+a.databaseName, a.gormConfig) } else if a.driverName == "sqlite3" { - db, err = openDBConnection(a.driverName, a.dataSourceName) + db, err = openDBConnection(a.driverName, a.dataSourceName, a.gormConfig) } else if a.driverName == "sqlserver" { - db, err = openDBConnection(a.driverName, a.dataSourceName+"?database="+a.databaseName) + db, err = openDBConnection(a.driverName, a.dataSourceName+"?database="+a.databaseName, a.gormConfig) } else { - db, err = openDBConnection(a.driverName, a.dataSourceName+a.databaseName) + db, err = openDBConnection(a.driverName, a.dataSourceName+a.databaseName, a.gormConfig) } if err != nil { return err diff --git a/adapter_test.go b/adapter_test.go index e0323f0..31e4975 100755 --- a/adapter_test.go +++ b/adapter_test.go @@ -1286,3 +1286,67 @@ func TestNewTransactionalAdapterConstructors(t *testing.T) { assert.NotNil(t, txContext2) txContext2.Rollback() // Clean up } + +func TestAdapterWithConfigWithoutSlowQueryLog(t *testing.T) { + // Test NewConfigWithoutSlowQueryLog helper function + config := NewConfigWithoutSlowQueryLog() + assert.NotNil(t, config) + assert.NotNil(t, config.Logger) + + // Test NewAdapterWithConfig with sqlite (no external dependencies) + a, err := NewAdapterWithConfig("sqlite3", "casbin_test_config.db", config) + if err != nil { + t.Fatal(err) + } + defer func() { + a.Close() + os.Remove("casbin_test_config.db") + }() + + // Initialize some policy + e, err := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv") + if err != nil { + t.Fatal(err) + } + + // Save policy to DB + err = a.SavePolicy(e.GetModel()) + if err != nil { + t.Fatal(err) + } + + // Load policy from DB - this should not produce slow query logs + e.ClearPolicy() + err = a.LoadPolicy(e.GetModel()) + if err != nil { + t.Fatal(err) + } + + // Verify policy was loaded correctly + testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}}) + + // Test with database name parameter + config2 := NewConfigWithoutSlowQueryLog() + a2, err := NewAdapterWithConfig("sqlite3", "casbin_test_config2.db", config2, "test_casbin_db") + if err != nil { + t.Fatal(err) + } + defer func() { + a2.Close() + os.Remove("casbin_test_config2.db") + }() + + // Initialize and test + err = a2.SavePolicy(e.GetModel()) + if err != nil { + t.Fatal(err) + } + + e.ClearPolicy() + err = a2.LoadPolicy(e.GetModel()) + if err != nil { + t.Fatal(err) + } + + testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}}) +} From b9fcf937507ce617008b6c6d845b4f5feff7a951 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 08:56:42 +0000 Subject: [PATCH 3/6] Format code with gofmt Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com> --- adapter.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adapter.go b/adapter.go index 8003dc6..117f811 100755 --- a/adapter.go +++ b/adapter.go @@ -408,7 +408,7 @@ func NewConfigWithoutSlowQueryLog() *gorm.Config { func openDBConnection(driverName, dataSourceName string, config ...*gorm.Config) (*gorm.DB, error) { var err error var db *gorm.DB - + // Use provided config or default var cfg *gorm.Config if len(config) > 0 && config[0] != nil { @@ -416,7 +416,7 @@ func openDBConnection(driverName, dataSourceName string, config ...*gorm.Config) } else { cfg = &gorm.Config{} } - + if driverName == "postgres" { db, err = gorm.Open(postgres.Open(dataSourceName), cfg) } else if driverName == "mysql" { From 0f912765cf9872efa4f1e24fb461b38c973a6b8e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 08:59:15 +0000 Subject: [PATCH 4/6] Refactor parameter parsing and improve type safety Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com> --- adapter.go | 131 +++++++++++++++++++++++------------------------------ 1 file changed, 57 insertions(+), 74 deletions(-) diff --git a/adapter.go b/adapter.go index 117f811..1873a18 100755 --- a/adapter.go +++ b/adapter.go @@ -119,29 +119,9 @@ func (dbPool *DbPool) switchDb(dbName string) *gorm.DB { return dbPool.source.Clauses(dbresolver.Write) } -// NewAdapter is the constructor for Adapter. -// Params : databaseName,tableName,dbSpecified -// -// databaseName,{tableName/dbSpecified} -// {database/dbSpecified} -// -// databaseName and tableName are user defined. -// Their default value are "casbin" and "casbin_rule" -// -// dbSpecified is an optional bool parameter. The default value is false. -// It's up to whether you have specified an existing DB in dataSourceName. -// If dbSpecified == true, you need to make sure the DB in dataSourceName exists. -// If dbSpecified == false, the adapter will automatically create a DB named databaseName. -func NewAdapter(driverName string, dataSourceName string, params ...interface{}) (*Adapter, error) { - a := &Adapter{} - a.driverName = driverName - a.dataSourceName = dataSourceName - - a.tableName = defaultTableName - a.databaseName = defaultDatabaseName - a.dbSpecified = false - a.transactionMu = &sync.Mutex{} - +// parseAdapterParams parses the optional parameters for adapter constructors. +// It sets the databaseName, tableName, and dbSpecified fields on the adapter. +func parseAdapterParams(a *Adapter, params ...interface{}) error { if len(params) == 1 { switch p1 := params[0].(type) { case bool: @@ -149,7 +129,7 @@ func NewAdapter(driverName string, dataSourceName string, params ...interface{}) case string: a.databaseName = p1 default: - return nil, errors.New("wrong format") + return errors.New("wrong format") } } else if len(params) == 2 { switch p2 := params[1].(type) { @@ -157,33 +137,71 @@ func NewAdapter(driverName string, dataSourceName string, params ...interface{}) a.dbSpecified = p2 p1, ok := params[0].(string) if !ok { - return nil, errors.New("wrong format") + return errors.New("wrong format") } a.databaseName = p1 case string: p1, ok := params[0].(string) if !ok { - return nil, errors.New("wrong format") + return errors.New("wrong format") } a.databaseName = p1 a.tableName = p2 default: - return nil, errors.New("wrong format") + return errors.New("wrong format") } } else if len(params) == 3 { - if p3, ok := params[2].(bool); ok { - a.dbSpecified = p3 - a.databaseName = params[0].(string) - a.tableName = params[1].(string) - } else { - return nil, errors.New("wrong format") + p3, ok := params[2].(bool) + if !ok { + return errors.New("wrong format") + } + p1, ok := params[0].(string) + if !ok { + return errors.New("wrong format") } + p2, ok := params[1].(string) + if !ok { + return errors.New("wrong format") + } + a.dbSpecified = p3 + a.databaseName = p1 + a.tableName = p2 } else if len(params) != 0 { - return nil, errors.New("too many parameters") + return errors.New("too many parameters") + } + return nil +} + +// NewAdapter is the constructor for Adapter. +// Params : databaseName,tableName,dbSpecified +// +// databaseName,{tableName/dbSpecified} +// {database/dbSpecified} +// +// databaseName and tableName are user defined. +// Their default value are "casbin" and "casbin_rule" +// +// dbSpecified is an optional bool parameter. The default value is false. +// It's up to whether you have specified an existing DB in dataSourceName. +// If dbSpecified == true, you need to make sure the DB in dataSourceName exists. +// If dbSpecified == false, the adapter will automatically create a DB named databaseName. +func NewAdapter(driverName string, dataSourceName string, params ...interface{}) (*Adapter, error) { + a := &Adapter{} + a.driverName = driverName + a.dataSourceName = dataSourceName + + a.tableName = defaultTableName + a.databaseName = defaultDatabaseName + a.dbSpecified = false + a.transactionMu = &sync.Mutex{} + + err := parseAdapterParams(a, params...) + if err != nil { + return nil, err } // Open the DB, create it if not existed. - err := a.Open() + err = a.Open() if err != nil { return nil, err } @@ -218,48 +236,13 @@ func NewAdapterWithConfig(driverName string, dataSourceName string, config *gorm a.dbSpecified = false a.transactionMu = &sync.Mutex{} - if len(params) == 1 { - switch p1 := params[0].(type) { - case bool: - a.dbSpecified = p1 - case string: - a.databaseName = p1 - default: - return nil, errors.New("wrong format") - } - } else if len(params) == 2 { - switch p2 := params[1].(type) { - case bool: - a.dbSpecified = p2 - p1, ok := params[0].(string) - if !ok { - return nil, errors.New("wrong format") - } - a.databaseName = p1 - case string: - p1, ok := params[0].(string) - if !ok { - return nil, errors.New("wrong format") - } - a.databaseName = p1 - a.tableName = p2 - default: - return nil, errors.New("wrong format") - } - } else if len(params) == 3 { - if p3, ok := params[2].(bool); ok { - a.dbSpecified = p3 - a.databaseName = params[0].(string) - a.tableName = params[1].(string) - } else { - return nil, errors.New("wrong format") - } - } else if len(params) != 0 { - return nil, errors.New("too many parameters") + err := parseAdapterParams(a, params...) + if err != nil { + return nil, err } // Open the DB, create it if not existed. - err := a.Open() + err = a.Open() if err != nil { return nil, err } From 5c36718d2b363e9543f9bdd7dd79999e3daaed54 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 09:01:17 +0000 Subject: [PATCH 5/6] Improve documentation clarity for NewAdapterWithConfig Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com> --- adapter.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/adapter.go b/adapter.go index 1873a18..fd78342 100755 --- a/adapter.go +++ b/adapter.go @@ -214,7 +214,12 @@ func NewAdapter(driverName string, dataSourceName string, params ...interface{}) // NewAdapterWithConfig is the constructor for Adapter with custom gorm.Config. // This allows you to customize GORM behavior, including disabling slow query logging. -// Params are the same as NewAdapter, with an additional config parameter. +// +// Parameters: +// - driverName: Database driver name (e.g., "mysql", "postgres", "sqlite3", "sqlserver") +// - dataSourceName: Database connection string +// - config: Custom gorm.Config (use NewConfigWithoutSlowQueryLog() to disable slow query logging) +// - params: Optional parameters same as NewAdapter (databaseName, tableName, dbSpecified) // // Example usage to disable slow query logging: // From fe68a13428156cb0b242ad18873e0a08edc31b71 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 09:10:32 +0000 Subject: [PATCH 6/6] Changes before error encountered Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com> --- README.md | 52 -------------- adapter.go | 179 +++++++++++++----------------------------------- adapter_test.go | 64 ----------------- 3 files changed, 46 insertions(+), 249 deletions(-) diff --git a/README.md b/README.md index 91b9546..ff2b04f 100644 --- a/README.md +++ b/README.md @@ -79,58 +79,6 @@ TurnOffAutoMigrate(db) a,_ := NewAdapterByDBWithCustomTable(...) ``` Find out more details at [gorm-adapter#162](https://github.com/casbin/gorm-adapter/issues/162) - -## Disable Slow Query Logging - -By default, GORM logs slow queries (queries taking more than 200ms). To disable this logging, you can use `NewAdapterWithConfig` with a custom logger configuration: - -```go -package main - -import ( - "github.com/casbin/casbin/v2" - gormadapter "github.com/casbin/gorm-adapter/v3" -) - -func main() { - // Create a config without slow query logging - config := gormadapter.NewConfigWithoutSlowQueryLog() - - // Initialize adapter with the config - a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config) - e, _ := casbin.NewEnforcer("examples/rbac_model.conf", a) - - // Load the policy from DB - no slow query logs will be printed - e.LoadPolicy() - - // Check the permission - e.Enforce("alice", "data1", "read") -} -``` - -You can also use `NewAdapterWithConfig` with database name and table name parameters, just like `NewAdapter`: - -```go -config := gormadapter.NewConfigWithoutSlowQueryLog() -// With database name -a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config, "casbin") -// With database name and table name -a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config, "casbin", "casbin_rule") -``` - -If you need more control over the logger, you can also create a custom `gorm.Config`: - -```go -import "gorm.io/gorm/logger" - -config := &gorm.Config{ - Logger: logger.Default.LogMode(logger.Silent), // Completely silent - // Or use logger.Error to only show errors: - // Logger: logger.Default.LogMode(logger.Error), -} -a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config) -``` - ## Customize table columns example You can change the gorm struct tags, but the table structure must stay the same. ```go diff --git a/adapter.go b/adapter.go index fd78342..ae5c6af 100755 --- a/adapter.go +++ b/adapter.go @@ -86,7 +86,6 @@ type Adapter struct { isFiltered bool transactionMu *sync.Mutex muInitialize sync.Once - gormConfig *gorm.Config } // finalizer is the destructor for Adapter. @@ -119,9 +118,29 @@ func (dbPool *DbPool) switchDb(dbName string) *gorm.DB { return dbPool.source.Clauses(dbresolver.Write) } -// parseAdapterParams parses the optional parameters for adapter constructors. -// It sets the databaseName, tableName, and dbSpecified fields on the adapter. -func parseAdapterParams(a *Adapter, params ...interface{}) error { +// NewAdapter is the constructor for Adapter. +// Params : databaseName,tableName,dbSpecified +// +// databaseName,{tableName/dbSpecified} +// {database/dbSpecified} +// +// databaseName and tableName are user defined. +// Their default value are "casbin" and "casbin_rule" +// +// dbSpecified is an optional bool parameter. The default value is false. +// It's up to whether you have specified an existing DB in dataSourceName. +// If dbSpecified == true, you need to make sure the DB in dataSourceName exists. +// If dbSpecified == false, the adapter will automatically create a DB named databaseName. +func NewAdapter(driverName string, dataSourceName string, params ...interface{}) (*Adapter, error) { + a := &Adapter{} + a.driverName = driverName + a.dataSourceName = dataSourceName + + a.tableName = defaultTableName + a.databaseName = defaultDatabaseName + a.dbSpecified = false + a.transactionMu = &sync.Mutex{} + if len(params) == 1 { switch p1 := params[0].(type) { case bool: @@ -129,7 +148,7 @@ func parseAdapterParams(a *Adapter, params ...interface{}) error { case string: a.databaseName = p1 default: - return errors.New("wrong format") + return nil, errors.New("wrong format") } } else if len(params) == 2 { switch p2 := params[1].(type) { @@ -137,117 +156,33 @@ func parseAdapterParams(a *Adapter, params ...interface{}) error { a.dbSpecified = p2 p1, ok := params[0].(string) if !ok { - return errors.New("wrong format") + return nil, errors.New("wrong format") } a.databaseName = p1 case string: p1, ok := params[0].(string) if !ok { - return errors.New("wrong format") + return nil, errors.New("wrong format") } a.databaseName = p1 a.tableName = p2 default: - return errors.New("wrong format") + return nil, errors.New("wrong format") } } else if len(params) == 3 { - p3, ok := params[2].(bool) - if !ok { - return errors.New("wrong format") - } - p1, ok := params[0].(string) - if !ok { - return errors.New("wrong format") - } - p2, ok := params[1].(string) - if !ok { - return errors.New("wrong format") + if p3, ok := params[2].(bool); ok { + a.dbSpecified = p3 + a.databaseName = params[0].(string) + a.tableName = params[1].(string) + } else { + return nil, errors.New("wrong format") } - a.dbSpecified = p3 - a.databaseName = p1 - a.tableName = p2 } else if len(params) != 0 { - return errors.New("too many parameters") - } - return nil -} - -// NewAdapter is the constructor for Adapter. -// Params : databaseName,tableName,dbSpecified -// -// databaseName,{tableName/dbSpecified} -// {database/dbSpecified} -// -// databaseName and tableName are user defined. -// Their default value are "casbin" and "casbin_rule" -// -// dbSpecified is an optional bool parameter. The default value is false. -// It's up to whether you have specified an existing DB in dataSourceName. -// If dbSpecified == true, you need to make sure the DB in dataSourceName exists. -// If dbSpecified == false, the adapter will automatically create a DB named databaseName. -func NewAdapter(driverName string, dataSourceName string, params ...interface{}) (*Adapter, error) { - a := &Adapter{} - a.driverName = driverName - a.dataSourceName = dataSourceName - - a.tableName = defaultTableName - a.databaseName = defaultDatabaseName - a.dbSpecified = false - a.transactionMu = &sync.Mutex{} - - err := parseAdapterParams(a, params...) - if err != nil { - return nil, err + return nil, errors.New("too many parameters") } // Open the DB, create it if not existed. - err = a.Open() - if err != nil { - return nil, err - } - - // Call the destructor when the object is released. - runtime.SetFinalizer(a, finalizer) - - return a, nil -} - -// NewAdapterWithConfig is the constructor for Adapter with custom gorm.Config. -// This allows you to customize GORM behavior, including disabling slow query logging. -// -// Parameters: -// - driverName: Database driver name (e.g., "mysql", "postgres", "sqlite3", "sqlserver") -// - dataSourceName: Database connection string -// - config: Custom gorm.Config (use NewConfigWithoutSlowQueryLog() to disable slow query logging) -// - params: Optional parameters same as NewAdapter (databaseName, tableName, dbSpecified) -// -// Example usage to disable slow query logging: -// -// config := gormadapter.NewConfigWithoutSlowQueryLog() -// a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config) -// -// Or with database name: -// -// config := gormadapter.NewConfigWithoutSlowQueryLog() -// a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config, "casbin") -func NewAdapterWithConfig(driverName string, dataSourceName string, config *gorm.Config, params ...interface{}) (*Adapter, error) { - a := &Adapter{} - a.driverName = driverName - a.dataSourceName = dataSourceName - a.gormConfig = config - - a.tableName = defaultTableName - a.databaseName = defaultDatabaseName - a.dbSpecified = false - a.transactionMu = &sync.Mutex{} - - err := parseAdapterParams(a, params...) - if err != nil { - return nil, err - } - - // Open the DB, create it if not existed. - err = a.Open() + err := a.Open() if err != nil { return nil, err } @@ -380,39 +315,17 @@ func NewAdapterByDBWithCustomTable(db *gorm.DB, t interface{}, tableName ...stri return NewAdapterByDBUseTableName(db.WithContext(ctx), "", curTableName) } -// NewConfigWithoutSlowQueryLog creates a gorm.Config with slow query logging disabled. -// This can be used to suppress GORM's slow SQL log output. -// -// Example usage: -// -// config := gormadapter.NewConfigWithoutSlowQueryLog() -// a, _ := gormadapter.NewAdapterWithConfig("mysql", "user:pass@tcp(127.0.0.1:3306)/", config) -func NewConfigWithoutSlowQueryLog() *gorm.Config { - return &gorm.Config{ - Logger: logger.Default.LogMode(logger.Silent), - } -} - -func openDBConnection(driverName, dataSourceName string, config ...*gorm.Config) (*gorm.DB, error) { +func openDBConnection(driverName, dataSourceName string) (*gorm.DB, error) { var err error var db *gorm.DB - - // Use provided config or default - var cfg *gorm.Config - if len(config) > 0 && config[0] != nil { - cfg = config[0] - } else { - cfg = &gorm.Config{} - } - if driverName == "postgres" { - db, err = gorm.Open(postgres.Open(dataSourceName), cfg) + db, err = gorm.Open(postgres.Open(dataSourceName), &gorm.Config{}) } else if driverName == "mysql" { - db, err = gorm.Open(mysql.Open(dataSourceName), cfg) + db, err = gorm.Open(mysql.Open(dataSourceName), &gorm.Config{}) } else if driverName == "sqlserver" { - db, err = gorm.Open(sqlserver.Open(dataSourceName), cfg) + db, err = gorm.Open(sqlserver.Open(dataSourceName), &gorm.Config{}) } else if driverName == "sqlite3" { - db, err = gorm.Open(sqlite.Open(dataSourceName), cfg) + db, err = gorm.Open(sqlite.Open(dataSourceName), &gorm.Config{}) } else { return nil, errors.New("Database dialect '" + driverName + "' is not supported. Supported databases are postgres, mysql, sqlserver and sqlite3") } @@ -424,7 +337,7 @@ func openDBConnection(driverName, dataSourceName string, config ...*gorm.Config) func (a *Adapter) createDatabase() error { var err error - db, err := openDBConnection(a.driverName, a.dataSourceName, a.gormConfig) + db, err := openDBConnection(a.driverName, a.dataSourceName) if err != nil { return err } @@ -449,7 +362,7 @@ func (a *Adapter) Open() error { var db *gorm.DB if a.dbSpecified { - db, err = openDBConnection(a.driverName, a.dataSourceName, a.gormConfig) + db, err = openDBConnection(a.driverName, a.dataSourceName) if err != nil { return err } @@ -458,13 +371,13 @@ func (a *Adapter) Open() error { return err } if a.driverName == "postgres" { - db, err = openDBConnection(a.driverName, a.dataSourceName+" dbname="+a.databaseName, a.gormConfig) + db, err = openDBConnection(a.driverName, a.dataSourceName+" dbname="+a.databaseName) } else if a.driverName == "sqlite3" { - db, err = openDBConnection(a.driverName, a.dataSourceName, a.gormConfig) + db, err = openDBConnection(a.driverName, a.dataSourceName) } else if a.driverName == "sqlserver" { - db, err = openDBConnection(a.driverName, a.dataSourceName+"?database="+a.databaseName, a.gormConfig) + db, err = openDBConnection(a.driverName, a.dataSourceName+"?database="+a.databaseName) } else { - db, err = openDBConnection(a.driverName, a.dataSourceName+a.databaseName, a.gormConfig) + db, err = openDBConnection(a.driverName, a.dataSourceName+a.databaseName) } if err != nil { return err diff --git a/adapter_test.go b/adapter_test.go index 31e4975..e0323f0 100755 --- a/adapter_test.go +++ b/adapter_test.go @@ -1286,67 +1286,3 @@ func TestNewTransactionalAdapterConstructors(t *testing.T) { assert.NotNil(t, txContext2) txContext2.Rollback() // Clean up } - -func TestAdapterWithConfigWithoutSlowQueryLog(t *testing.T) { - // Test NewConfigWithoutSlowQueryLog helper function - config := NewConfigWithoutSlowQueryLog() - assert.NotNil(t, config) - assert.NotNil(t, config.Logger) - - // Test NewAdapterWithConfig with sqlite (no external dependencies) - a, err := NewAdapterWithConfig("sqlite3", "casbin_test_config.db", config) - if err != nil { - t.Fatal(err) - } - defer func() { - a.Close() - os.Remove("casbin_test_config.db") - }() - - // Initialize some policy - e, err := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv") - if err != nil { - t.Fatal(err) - } - - // Save policy to DB - err = a.SavePolicy(e.GetModel()) - if err != nil { - t.Fatal(err) - } - - // Load policy from DB - this should not produce slow query logs - e.ClearPolicy() - err = a.LoadPolicy(e.GetModel()) - if err != nil { - t.Fatal(err) - } - - // Verify policy was loaded correctly - testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}}) - - // Test with database name parameter - config2 := NewConfigWithoutSlowQueryLog() - a2, err := NewAdapterWithConfig("sqlite3", "casbin_test_config2.db", config2, "test_casbin_db") - if err != nil { - t.Fatal(err) - } - defer func() { - a2.Close() - os.Remove("casbin_test_config2.db") - }() - - // Initialize and test - err = a2.SavePolicy(e.GetModel()) - if err != nil { - t.Fatal(err) - } - - e.ClearPolicy() - err = a2.LoadPolicy(e.GetModel()) - if err != nil { - t.Fatal(err) - } - - testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}}) -}