diff --git a/postgres-examples/README.md b/postgres-examples/README.md index fccc338bd..93f76e378 100644 --- a/postgres-examples/README.md +++ b/postgres-examples/README.md @@ -9,10 +9,10 @@ This directory contains examples demonstrating how to connect to SeaweedFS using weed postgres -port=5432 -master=localhost:9333 # Start with password authentication -weed postgres -port=5432 -auth=password -users="admin:secret,readonly:view123" +weed postgres -port=5432 -auth=password -users="admin:secret;readonly:view123" # Start with MD5 authentication (more secure) -weed postgres -port=5432 -auth=md5 -users="user1:pass1,user2:pass2" +weed postgres -port=5432 -auth=md5 -users="user1:pass1;user2:pass2" # Start with TLS encryption weed postgres -port=5432 -tls-cert=server.crt -tls-key=server.key diff --git a/weed/command/db.go b/weed/command/db.go index 5a315276b..84027f167 100644 --- a/weed/command/db.go +++ b/weed/command/db.go @@ -37,7 +37,7 @@ func init() { dbOptions.port = cmdDB.Flag.Int("port", 5432, "Database server port") dbOptions.masterAddr = cmdDB.Flag.String("master", "localhost:9333", "SeaweedFS master server address") dbOptions.authMethod = cmdDB.Flag.String("auth", "trust", "Authentication method: trust, password, md5") - dbOptions.users = cmdDB.Flag.String("users", "", "User credentials for auth (format: user1:pass1,user2:pass2)") + dbOptions.users = cmdDB.Flag.String("users", "", "User credentials for auth (format: user1:pass1;user2:pass2)") dbOptions.database = cmdDB.Flag.String("database", "default", "Default database name") dbOptions.maxConns = cmdDB.Flag.Int("max-connections", 100, "Maximum concurrent connections") dbOptions.idleTimeout = cmdDB.Flag.String("idle-timeout", "1h", "Connection idle timeout") @@ -60,10 +60,10 @@ Examples: weed db # Start with password authentication - weed db -auth=password -users="admin:secret,readonly:view123" + weed db -auth=password -users="admin:secret;readonly:view123" # Start with MD5 authentication - weed db -auth=md5 -users="user1:pass1,user2:pass2" + weed db -auth=md5 -users="user1:pass1;user2:pass2" # Start with custom port and master weed db -port=5433 -master=master1:9333 @@ -315,6 +315,8 @@ func parseAuthMethod(method string) (postgres.AuthMethod, error) { } // parseUsers parses the user credentials string +// Format: username:password;username2:password2 +// Semicolons are used as separators to avoid conflicts with commas that may appear in passwords func parseUsers(usersStr string, authMethod postgres.AuthMethod) (map[string]string, error) { users := make(map[string]string) @@ -326,8 +328,24 @@ func parseUsers(usersStr string, authMethod postgres.AuthMethod) (map[string]str return users, nil } - // Parse user:password pairs - pairs := strings.Split(usersStr, ",") + // Parse user:password pairs separated by semicolons (safer than commas for passwords) + // Also support legacy comma format for backward compatibility + var pairs []string + if strings.Contains(usersStr, ";") { + pairs = strings.Split(usersStr, ";") + } else { + // Legacy comma format - warn about potential issues + pairs = strings.Split(usersStr, ",") + if len(pairs) > 1 { + // Only warn if there are actually multiple pairs + for _, pair := range pairs { + if strings.Count(pair, ":") > 1 { + return nil, fmt.Errorf("detected multiple colons in user specification '%s'. This may indicate a password containing commas. Please use semicolons (;) to separate user:password pairs instead of commas", pair) + } + } + } + } + for _, pair := range pairs { pair = strings.TrimSpace(pair) if pair == "" { diff --git a/weed/command/sql.go b/weed/command/sql.go index 0d14a5984..7c85173ff 100644 --- a/weed/command/sql.go +++ b/weed/command/sql.go @@ -286,8 +286,17 @@ func runInteractiveShell(ctx *SQLContext) bool { // Handle database switching parts := strings.Fields(cleanQuery) if len(parts) >= 2 && strings.ToUpper(parts[0]) == "USE" { - // Extract database name preserving original case - dbName := strings.TrimSpace(parts[1]) + // Re-join the parts after "USE" to handle names with spaces, then trim. + dbName := strings.TrimSpace(strings.TrimPrefix(cleanQuery, parts[0])) + + // Unquote if necessary (handle quoted identifiers like "my-database") + if len(dbName) > 1 && dbName[0] == '"' && dbName[len(dbName)-1] == '"' { + dbName = dbName[1 : len(dbName)-1] + } else if len(dbName) > 1 && dbName[0] == '`' && dbName[len(dbName)-1] == '`' { + // Also handle backtick quotes for MySQL compatibility + dbName = dbName[1 : len(dbName)-1] + } + ctx.currentDatabase = dbName // Also update the SQL engine's catalog current database ctx.engine.GetCatalog().SetCurrentDatabase(dbName) diff --git a/weed/server/postgres/DESIGN.md b/weed/server/postgres/DESIGN.md index 20a89be6d..33d922a43 100644 --- a/weed/server/postgres/DESIGN.md +++ b/weed/server/postgres/DESIGN.md @@ -297,14 +297,14 @@ jdbc:postgresql://localhost:5432/default?user=seaweedfs&password=secret ```bash # Start PostgreSQL protocol server weed db -port=5432 -auth=trust -weed db -port=5432 -auth=password -users="admin:secret,readonly:pass" +weed db -port=5432 -auth=password -users="admin:secret;readonly:pass" weed db -port=5432 -tls-cert=server.crt -tls-key=server.key # Configuration options -host=localhost # Listen host -port=5432 # PostgreSQL standard port -auth=trust|password|md5 # Authentication method --users=user:pass,user2:pass2 # User credentials (password/md5 auth) +-users=user:pass;user2:pass2 # User credentials (password/md5 auth) - use semicolons to separate users -database=default # Default database name -max-connections=100 # Maximum concurrent connections -idle-timeout=1h # Connection idle timeout