diff --git a/redshift/config.go b/redshift/config.go index 9519fc0..8ac7098 100644 --- a/redshift/config.go +++ b/redshift/config.go @@ -24,6 +24,9 @@ type Config struct { Database string SSLMode string MaxConns int + + isServerless bool + checkedForServerless bool } // Client struct holding connection string @@ -48,6 +51,29 @@ func (c *Config) NewClient(database string) *Client { } } +func (c *Config) IsServerless(db *DBConnection) (bool, error) { + if c.checkedForServerless { + return c.isServerless, nil + } + + c.checkedForServerless = true + + _, err := db.Query("SELECT 1 FROM SYS_SERVERLESS_USAGE") + // No error means we have accessed the view and are running Redshift Serverless + if err == nil { + c.isServerless = true + return true, nil + } + + // Insuficcient privileges means we do not have access to this view ergo we run on Redshift classic + if isPqErrorWithCode(err, pgErrorCodeInsufficientPrivileges) { + c.isServerless = false + return false, nil + } + + return false, err +} + // Connect returns a copy to an sql.Open()'ed database connection wrapped in a DBConnection struct. // Callers must return their database resources. Use of QueryRow() or Exec() is encouraged. // Query() must have their rows.Close()'ed. diff --git a/redshift/helpers.go b/redshift/helpers.go index f8df5dc..8bc0d8e 100644 --- a/redshift/helpers.go +++ b/redshift/helpers.go @@ -18,6 +18,8 @@ const ( pqErrorCodeDeadlock = "40P01" pqErrorCodeFailedTransaction = "25P02" pqErrorCodeDuplicateSchema = "42P06" + + pgErrorCodeInsufficientPrivileges = "42501" ) // startTransaction starts a new DB transaction on the specified database. @@ -134,6 +136,10 @@ func isRetryablePQError(code string) bool { return ok } +func isPqErrorWithCode(err error, code string) bool { + return string(err.(*pq.Error).Code) == code +} + func splitCsvAndTrim(raw string) ([]string, error) { if raw == "" { return []string{}, nil diff --git a/redshift/resource_redshift_schema.go b/redshift/resource_redshift_schema.go index ae1378f..7244a08 100644 --- a/redshift/resource_redshift_schema.go +++ b/redshift/resource_redshift_schema.go @@ -449,21 +449,23 @@ func resourceRedshiftSchemaReadImpl(db *DBConnection, d *schema.ResourceData) er } func resourceRedshiftSchemaReadLocal(db *DBConnection, d *schema.ResourceData) error { - var schemaQuota int - - err := db.QueryRow(` - SELECT - COALESCE(quota, 0) - FROM svv_schema_quota_state - WHERE schema_id = $1 - `, d.Id()).Scan(&schemaQuota) - switch { - case err == sql.ErrNoRows: - schemaQuota = 0 - case err != nil: + var schemaQuota int = 0 + isServerless, err := db.client.config.IsServerless(db) + if err != nil { return err } + if !isServerless { + err := db.QueryRow(` + SELECT + COALESCE(quota, 0) + FROM svv_schema_quota_state + WHERE schema_id = $1 + `, d.Id()).Scan(&schemaQuota) + if err != nil && err != sql.ErrNoRows { + return err + } + } d.Set(schemaQuotaAttr, schemaQuota) d.Set(schemaExternalSchemaAttr, nil) diff --git a/redshift/resource_redshift_user.go b/redshift/resource_redshift_user.go index 731a5f4..277716d 100644 --- a/redshift/resource_redshift_user.go +++ b/redshift/resource_redshift_user.go @@ -274,12 +274,12 @@ func resourceRedshiftUserReadImpl(db *DBConnection, d *schema.ResourceData) erro var userSuperuser, userCreateDB bool columns := []string{ - "usename", - "usecreatedb", - "usesuper", - "syslogaccess", - `COALESCE(useconnlimit::TEXT, 'UNLIMITED')`, - "sessiontimeout", + "user_name", + "createdb", + "superuser", + "syslog_access", + `COALESCE(connection_limit::TEXT, 'UNLIMITED')`, + "session_timeout", } values := []interface{}{ @@ -293,7 +293,7 @@ func resourceRedshiftUserReadImpl(db *DBConnection, d *schema.ResourceData) erro useSysID := d.Id() - userSQL := fmt.Sprintf("SELECT %s FROM svl_user_info WHERE usesysid = $1", strings.Join(columns, ",")) + userSQL := fmt.Sprintf("SELECT %s FROM svv_user_info WHERE user_id = $1", strings.Join(columns, ",")) err := db.QueryRow(userSQL, useSysID).Scan(values...) switch { case err == sql.ErrNoRows: