@@ -16,23 +16,24 @@ import (
1616)
1717
1818const (
19- roleBypassRLSAttr = "bypass_row_level_security"
20- roleConnLimitAttr = "connection_limit"
21- roleCreateDBAttr = "create_database"
22- roleCreateRoleAttr = "create_role"
23- roleEncryptedPassAttr = "encrypted_password"
24- roleInheritAttr = "inherit"
25- roleLoginAttr = "login"
26- roleNameAttr = "name"
27- rolePasswordAttr = "password"
28- roleReplicationAttr = "replication"
29- roleSkipDropRoleAttr = "skip_drop_role"
30- roleSkipReassignOwnedAttr = "skip_reassign_owned"
31- roleSuperuserAttr = "superuser"
32- roleValidUntilAttr = "valid_until"
33- roleRolesAttr = "roles"
34- roleSearchPathAttr = "search_path"
35- roleStatementTimeoutAttr = "statement_timeout"
19+ roleBypassRLSAttr = "bypass_row_level_security"
20+ roleConnLimitAttr = "connection_limit"
21+ roleCreateDBAttr = "create_database"
22+ roleCreateRoleAttr = "create_role"
23+ roleEncryptedPassAttr = "encrypted_password"
24+ roleIdleInTransactionSessionTimeoutAttr = "idle_in_transaction_session_timeout"
25+ roleInheritAttr = "inherit"
26+ roleLoginAttr = "login"
27+ roleNameAttr = "name"
28+ rolePasswordAttr = "password"
29+ roleReplicationAttr = "replication"
30+ roleSkipDropRoleAttr = "skip_drop_role"
31+ roleSkipReassignOwnedAttr = "skip_reassign_owned"
32+ roleSuperuserAttr = "superuser"
33+ roleValidUntilAttr = "valid_until"
34+ roleRolesAttr = "roles"
35+ roleSearchPathAttr = "search_path"
36+ roleStatementTimeoutAttr = "statement_timeout"
3637
3738 // Deprecated options
3839 roleDepEncryptedAttr = "encrypted"
@@ -118,6 +119,12 @@ func resourcePostgreSQLRole() *schema.Resource {
118119 Default : false ,
119120 Description : "Determine whether this role will be permitted to create new roles" ,
120121 },
122+ roleIdleInTransactionSessionTimeoutAttr : {
123+ Type : schema .TypeInt ,
124+ Optional : true ,
125+ Description : "Terminate any session with an open transaction that has been idle for longer than the specified duration in milliseconds" ,
126+ ValidateFunc : validation .IntAtLeast (0 ),
127+ },
121128 roleInheritAttr : {
122129 Type : schema .TypeBool ,
123130 Optional : true ,
@@ -290,6 +297,10 @@ func resourcePostgreSQLRoleCreate(db *DBConnection, d *schema.ResourceData) erro
290297 return err
291298 }
292299
300+ if err = setIdleInTransactionSessionTimeout (txn , d ); err != nil {
301+ return err
302+ }
303+
293304 if err = txn .Commit (); err != nil {
294305 return fmt .Errorf ("could not commit transaction: %w" , err )
295306 }
@@ -439,6 +450,13 @@ func resourcePostgreSQLRoleReadImpl(db *DBConnection, d *schema.ResourceData) er
439450
440451 d .Set (roleStatementTimeoutAttr , statementTimeout )
441452
453+ idleInTransactionSessionTimeout , err := readIdleInTransactionSessionTimeout (roleConfig )
454+ if err != nil {
455+ return err
456+ }
457+
458+ d .Set (roleIdleInTransactionSessionTimeoutAttr , idleInTransactionSessionTimeout )
459+
442460 d .SetId (roleName )
443461
444462 password , err := readRolePassword (db , d , roleCanLogin )
@@ -466,6 +484,23 @@ func readSearchPath(roleConfig pq.ByteaArray) []string {
466484 return nil
467485}
468486
487+ // readIdleInTransactionSessionTimeout searches for a idle_in_transaction_session_timeout entry in the rolconfig array.
488+ // In case no such value is present, it returns nil.
489+ func readIdleInTransactionSessionTimeout (roleConfig pq.ByteaArray ) (int , error ) {
490+ for _ , v := range roleConfig {
491+ config := string (v )
492+ if strings .HasPrefix (config , roleIdleInTransactionSessionTimeoutAttr ) {
493+ var result = strings .Split (strings .TrimPrefix (config , roleIdleInTransactionSessionTimeoutAttr + "=" ), ", " )
494+ res , err := strconv .Atoi (result [0 ])
495+ if err != nil {
496+ return - 1 , fmt .Errorf ("Error reading statement_timeout: %w" , err )
497+ }
498+ return res , nil
499+ }
500+ }
501+ return 0 , nil
502+ }
503+
469504// readStatementTimeout searches for a statement_timeout entry in the rolconfig array.
470505// In case no such value is present, it returns nil.
471506func readStatementTimeout (roleConfig pq.ByteaArray ) (int , error ) {
@@ -610,6 +645,10 @@ func resourcePostgreSQLRoleUpdate(db *DBConnection, d *schema.ResourceData) erro
610645 return err
611646 }
612647
648+ if err = setIdleInTransactionSessionTimeout (txn , d ); err != nil {
649+ return err
650+ }
651+
613652 if err = txn .Commit (); err != nil {
614653 return fmt .Errorf ("could not commit transaction: %w" , err )
615654 }
@@ -933,3 +972,28 @@ func setStatementTimeout(txn *sql.Tx, d *schema.ResourceData) error {
933972 }
934973 return nil
935974}
975+
976+ func setIdleInTransactionSessionTimeout (txn * sql.Tx , d * schema.ResourceData ) error {
977+ if ! d .HasChange (roleIdleInTransactionSessionTimeoutAttr ) {
978+ return nil
979+ }
980+
981+ roleName := d .Get (roleNameAttr ).(string )
982+ idleInTransactionSessionTimeout := d .Get (roleIdleInTransactionSessionTimeoutAttr ).(int )
983+ if idleInTransactionSessionTimeout != 0 {
984+ sql := fmt .Sprintf (
985+ "ALTER ROLE %s SET idle_in_transaction_session_timeout TO %d" , pq .QuoteIdentifier (roleName ), idleInTransactionSessionTimeout ,
986+ )
987+ if _ , err := txn .Exec (sql ); err != nil {
988+ return fmt .Errorf ("could not set idle_in_transaction_session_timeout %d for %s: %w" , idleInTransactionSessionTimeout , roleName , err )
989+ }
990+ } else {
991+ sql := fmt .Sprintf (
992+ "ALTER ROLE %s RESET idle_in_transaction_session_timeout" , pq .QuoteIdentifier (roleName ),
993+ )
994+ if _ , err := txn .Exec (sql ); err != nil {
995+ return fmt .Errorf ("could not reset idle_in_transaction_session_timeout for %s: %w" , roleName , err )
996+ }
997+ }
998+ return nil
999+ }
0 commit comments