19
19
Any charm using this library should import the `psycopg2` or `psycopg2-binary` dependency.
20
20
"""
21
21
import logging
22
- from typing import List , Optional , Set , Tuple
22
+ from typing import Dict , List , Optional , Set , Tuple
23
23
24
24
import psycopg2
25
25
from psycopg2 import sql
32
32
33
33
# Increment this PATCH version before using `charmcraft publish-lib` or reset
34
34
# to 0 if you are raising the major API version
35
- LIBPATCH = 14
35
+ LIBPATCH = 17
36
36
37
37
INVALID_EXTRA_USER_ROLE_BLOCKING_MESSAGE = "invalid role(s) for extra user roles"
38
38
@@ -117,12 +117,13 @@ def _connect_to_database(
117
117
connection .autocommit = True
118
118
return connection
119
119
120
- def create_database (self , database : str , user : str ) -> None :
120
+ def create_database (self , database : str , user : str , plugins : List [ str ] = [] ) -> None :
121
121
"""Creates a new database and grant privileges to a user on it.
122
122
123
123
Args:
124
124
database: database to be created.
125
125
user: user that will have access to the database.
126
+ plugins: extensions to enable in the new database.
126
127
"""
127
128
try :
128
129
connection = self ._connect_to_database ()
@@ -170,6 +171,10 @@ def create_database(self, database: str, user: str) -> None:
170
171
logger .error (f"Failed to create database: { e } " )
171
172
raise PostgreSQLCreateDatabaseError ()
172
173
174
+ # Enable preset extensions
175
+ for plugin in plugins :
176
+ self .enable_disable_extension (plugin , True , database )
177
+
173
178
def create_user (
174
179
self , user : str , password : str = None , admin : bool = False , extra_user_roles : str = None
175
180
) -> None :
@@ -406,6 +411,7 @@ def update_user_password(self, username: str, password: str) -> None:
406
411
Raises:
407
412
PostgreSQLUpdateUserPasswordError if the password couldn't be changed.
408
413
"""
414
+ connection = None
409
415
try :
410
416
with self ._connect_to_database () as connection , connection .cursor () as cursor :
411
417
cursor .execute (
@@ -420,19 +426,39 @@ def update_user_password(self, username: str, password: str) -> None:
420
426
if connection is not None :
421
427
connection .close ()
422
428
429
+ def is_restart_pending (self ) -> bool :
430
+ """Query pg_settings for pending restart."""
431
+ connection = None
432
+ try :
433
+ with self ._connect_to_database () as connection , connection .cursor () as cursor :
434
+ cursor .execute ("SELECT COUNT(*) FROM pg_settings WHERE pending_restart=True;" )
435
+ return cursor .fetchone ()[0 ] > 0
436
+ except psycopg2 .OperationalError :
437
+ logger .warning ("Failed to connect to PostgreSQL." )
438
+ return False
439
+ except psycopg2 .Error as e :
440
+ logger .error (f"Failed to check if restart is pending: { e } " )
441
+ return False
442
+ finally :
443
+ if connection :
444
+ connection .close ()
445
+
423
446
@staticmethod
424
447
def build_postgresql_parameters (
425
- profile : str , available_memory : int
426
- ) -> Optional [dict [str , str ]]:
448
+ profile : str , available_memory : int , limit_memory : Optional [ int ] = None
449
+ ) -> Optional [Dict [str , str ]]:
427
450
"""Builds the PostgreSQL parameters.
428
451
429
452
Args:
430
453
profile: the profile to use.
431
454
available_memory: available memory to use in calculation in bytes.
455
+ limit_memory: (optional) limit memory to use in calculation in bytes.
432
456
433
457
Returns:
434
458
Dictionary with the PostgreSQL parameters.
435
459
"""
460
+ if limit_memory :
461
+ available_memory = min (available_memory , limit_memory )
436
462
logger .debug (f"Building PostgreSQL parameters for { profile = } and { available_memory = } " )
437
463
if profile == "production" :
438
464
# Use 25% of the available memory for shared_buffers.
@@ -446,3 +472,6 @@ def build_postgresql_parameters(
446
472
}
447
473
448
474
return parameters
475
+ else :
476
+ # Return default
477
+ return {"shared_buffers" : "128MB" }
0 commit comments