@@ -123,6 +123,8 @@ createdb(const CreatedbStmt *stmt)
123123 DefElem * dencoding = NULL ;
124124 DefElem * dcollate = NULL ;
125125 DefElem * dctype = NULL ;
126+ DefElem * distemplate = NULL ;
127+ DefElem * dallowconnections = NULL ;
126128 DefElem * dconnlimit = NULL ;
127129 char * dbname = stmt -> dbname ;
128130 char * dbowner = NULL ;
@@ -131,6 +133,8 @@ createdb(const CreatedbStmt *stmt)
131133 char * dbctype = NULL ;
132134 char * canonname ;
133135 int encoding = -1 ;
136+ bool dbistemplate = false;
137+ bool dballowconnections = true;
134138 int dbconnlimit = -1 ;
135139 int notherbackends ;
136140 int npreparedxacts ;
@@ -189,6 +193,22 @@ createdb(const CreatedbStmt *stmt)
189193 errmsg ("conflicting or redundant options" )));
190194 dctype = defel ;
191195 }
196+ else if (strcmp (defel -> defname , "is_template" ) == 0 )
197+ {
198+ if (distemplate )
199+ ereport (ERROR ,
200+ (errcode (ERRCODE_SYNTAX_ERROR ),
201+ errmsg ("conflicting or redundant options" )));
202+ distemplate = defel ;
203+ }
204+ else if (strcmp (defel -> defname , "allow_connections" ) == 0 )
205+ {
206+ if (dallowconnections )
207+ ereport (ERROR ,
208+ (errcode (ERRCODE_SYNTAX_ERROR ),
209+ errmsg ("conflicting or redundant options" )));
210+ dallowconnections = defel ;
211+ }
192212 else if (strcmp (defel -> defname , "connection_limit" ) == 0 )
193213 {
194214 if (dconnlimit )
@@ -244,7 +264,10 @@ createdb(const CreatedbStmt *stmt)
244264 dbcollate = defGetString (dcollate );
245265 if (dctype && dctype -> arg )
246266 dbctype = defGetString (dctype );
247-
267+ if (distemplate && distemplate -> arg )
268+ dbistemplate = defGetBoolean (distemplate );
269+ if (dallowconnections && dallowconnections -> arg )
270+ dballowconnections = defGetBoolean (dallowconnections );
248271 if (dconnlimit && dconnlimit -> arg )
249272 {
250273 dbconnlimit = defGetInt32 (dconnlimit );
@@ -487,8 +510,8 @@ createdb(const CreatedbStmt *stmt)
487510 DirectFunctionCall1 (namein , CStringGetDatum (dbcollate ));
488511 new_record [Anum_pg_database_datctype - 1 ] =
489512 DirectFunctionCall1 (namein , CStringGetDatum (dbctype ));
490- new_record [Anum_pg_database_datistemplate - 1 ] = BoolGetDatum (false );
491- new_record [Anum_pg_database_datallowconn - 1 ] = BoolGetDatum (true );
513+ new_record [Anum_pg_database_datistemplate - 1 ] = BoolGetDatum (dbistemplate );
514+ new_record [Anum_pg_database_datallowconn - 1 ] = BoolGetDatum (dballowconnections );
492515 new_record [Anum_pg_database_datconnlimit - 1 ] = Int32GetDatum (dbconnlimit );
493516 new_record [Anum_pg_database_datlastsysoid - 1 ] = ObjectIdGetDatum (src_lastsysoid );
494517 new_record [Anum_pg_database_datfrozenxid - 1 ] = TransactionIdGetDatum (src_frozenxid );
@@ -1328,7 +1351,11 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
13281351 ScanKeyData scankey ;
13291352 SysScanDesc scan ;
13301353 ListCell * option ;
1331- int connlimit = -1 ;
1354+ bool dbistemplate = false;
1355+ bool dballowconnections = true;
1356+ int dbconnlimit = -1 ;
1357+ DefElem * distemplate = NULL ;
1358+ DefElem * dallowconnections = NULL ;
13321359 DefElem * dconnlimit = NULL ;
13331360 DefElem * dtablespace = NULL ;
13341361 Datum new_record [Natts_pg_database ];
@@ -1340,7 +1367,23 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
13401367 {
13411368 DefElem * defel = (DefElem * ) lfirst (option );
13421369
1343- if (strcmp (defel -> defname , "connection_limit" ) == 0 )
1370+ if (strcmp (defel -> defname , "is_template" ) == 0 )
1371+ {
1372+ if (distemplate )
1373+ ereport (ERROR ,
1374+ (errcode (ERRCODE_SYNTAX_ERROR ),
1375+ errmsg ("conflicting or redundant options" )));
1376+ distemplate = defel ;
1377+ }
1378+ else if (strcmp (defel -> defname , "allow_connections" ) == 0 )
1379+ {
1380+ if (dallowconnections )
1381+ ereport (ERROR ,
1382+ (errcode (ERRCODE_SYNTAX_ERROR ),
1383+ errmsg ("conflicting or redundant options" )));
1384+ dallowconnections = defel ;
1385+ }
1386+ else if (strcmp (defel -> defname , "connection_limit" ) == 0 )
13441387 {
13451388 if (dconnlimit )
13461389 ereport (ERROR ,
@@ -1380,13 +1423,17 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
13801423 return InvalidOid ;
13811424 }
13821425
1426+ if (distemplate && distemplate -> arg )
1427+ dbistemplate = defGetBoolean (distemplate );
1428+ if (dallowconnections && dallowconnections -> arg )
1429+ dballowconnections = defGetBoolean (dallowconnections );
13831430 if (dconnlimit && dconnlimit -> arg )
13841431 {
1385- connlimit = defGetInt32 (dconnlimit );
1386- if (connlimit < -1 )
1432+ dbconnlimit = defGetInt32 (dconnlimit );
1433+ if (dbconnlimit < -1 )
13871434 ereport (ERROR ,
13881435 (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1389- errmsg ("invalid connection limit: %d" , connlimit )));
1436+ errmsg ("invalid connection limit: %d" , dbconnlimit )));
13901437 }
13911438
13921439 /*
@@ -1413,16 +1460,37 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
14131460 aclcheck_error (ACLCHECK_NOT_OWNER , ACL_KIND_DATABASE ,
14141461 stmt -> dbname );
14151462
1463+ /*
1464+ * In order to avoid getting locked out and having to go through
1465+ * standalone mode, we refuse to disallow connections to the database
1466+ * we're currently connected to. Lockout can still happen with concurrent
1467+ * sessions but the likeliness of that is not high enough to worry about.
1468+ */
1469+ if (!dballowconnections && dboid == MyDatabaseId )
1470+ ereport (ERROR ,
1471+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1472+ errmsg ("cannot disallow connections for current database" )));
1473+
14161474 /*
14171475 * Build an updated tuple, perusing the information just obtained
14181476 */
14191477 MemSet (new_record , 0 , sizeof (new_record ));
14201478 MemSet (new_record_nulls , false, sizeof (new_record_nulls ));
14211479 MemSet (new_record_repl , false, sizeof (new_record_repl ));
14221480
1481+ if (distemplate )
1482+ {
1483+ new_record [Anum_pg_database_datistemplate - 1 ] = BoolGetDatum (dbistemplate );
1484+ new_record_repl [Anum_pg_database_datistemplate - 1 ] = true;
1485+ }
1486+ if (dallowconnections )
1487+ {
1488+ new_record [Anum_pg_database_datallowconn - 1 ] = BoolGetDatum (dballowconnections );
1489+ new_record_repl [Anum_pg_database_datallowconn - 1 ] = true;
1490+ }
14231491 if (dconnlimit )
14241492 {
1425- new_record [Anum_pg_database_datconnlimit - 1 ] = Int32GetDatum (connlimit );
1493+ new_record [Anum_pg_database_datconnlimit - 1 ] = Int32GetDatum (dbconnlimit );
14261494 new_record_repl [Anum_pg_database_datconnlimit - 1 ] = true;
14271495 }
14281496
0 commit comments