* Fix btree to give a useful elog when key > 1/2 (page - overhead)
* -pg_dump should preserve primary key information
* plpgsql regression tests fail on BSD/OS
-* database names with spaces fail
+* -database names with spaces fail
* insert of 0.0 into DECIMAL(4,4) field fails
ENHANCEMENTS
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_database.sgml,v 1.10 1999/12/04 04:53:15 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_database.sgml,v 1.11 1999/12/12 05:15:09 momjian Exp $
Postgres documentation
-->
</refnamediv>
<refsynopsisdiv>
<refsynopsisdivinfo>
- <date>1999-07-20</date>
+ <date>1999-12-11</date>
</refsynopsisdivinfo>
<synopsis>
CREATE DATABASE <replaceable class="PARAMETER">name</replaceable> [ WITH LOCATION = '<replaceable class="parameter">dbpath</replaceable>' ]
<refsect2 id="R2-SQL-CREATEDATABASE-1">
<refsect2info>
- <date>1998-04-15</date>
+ <date>1999-12-11</date>
</refsect2info>
<title>
Inputs
<term><replaceable class="parameter">dbpath</replaceable></term>
<listitem>
<para>
- An alternate location for the new database. See below for caveats.
+ An alternate location where to store the new database in the filesystem.
+ See below for caveats.
</para>
</listitem>
</varlistentry>
<refsect2 id="R2-SQL-CREATEDATABASE-2">
<refsect2info>
- <date>1998-04-15</date>
+ <date>1999-12-11</date>
</refsect2info>
<title>
Outputs
<variablelist>
<varlistentry>
- <term><computeroutput>
-CREATE DATABASE
- </computeroutput></term>
+ <term><computeroutput>CREATE DATABASE</computeroutput></term>
<listitem>
<para>
Message returned if the command completes successfully.
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>ERROR: user '<replaceable class="parameter">username</replaceable>' is not allowed to create/drop databases</computeroutput></term>
+ <listitem>
+ <para>
+ You must have the special CREATEDB privilege to create databases.
+ See <xref linkend="SQL-CREATEUSER" endterm="SQL-CREATEUSER-title">.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term><computeroutput>ERROR: createdb: database "<replaceable class="parameter">name</replaceable>" already exists</computeroutput></term>
+ <listitem>
+ <para>
+ This occurs if a database with the <replaceable class="parameter">name</replaceable>
+ specified already exists.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
- <term><computeroutput>
-WARN: createdb: database "<replaceable class="parameter">name</replaceable>" already exists.
- </computeroutput></term>
+ <term><computeroutput>ERROR: Single quotes are not allowed in database names.</computeroutput></term>
+ <term><computeroutput>ERROR: Single quotes are not allowed in database paths.</computeroutput></term>
<listitem>
<para>
- This occurs if <replaceable class="parameter">database</replaceable> specified already exists.
+ The database <replaceable class="parameter">name</replaceable> and
+ <replaceable class="parameter">dbpath</replaceable> cannot contain
+ single quotes. This is required so that the shell commands that
+ create the database directory can execute safely.
</para>
</listitem>
</varlistentry>
+
<varlistentry>
- <term><computeroutput>
-ERROR: Unable to create database directory <replaceable class="parameter">directory</replaceable>
- </computeroutput></term>
+ <term><computeroutput>ERROR: The path 'xxx' is invalid.</computeroutput></term>
<listitem>
<para>
- There was a problem with creating the required directory; this operation will
- need permissions for the <literal>postgres</literal> user on the specified location.
+ The expansion of the specified <replaceable class="parameter">dbpath</replaceable>
+ (see below how) failed. Check the path you entered or make sure that the
+ environment variable you are referencing does exist.
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>ERROR: createdb: May not be called in a transaction block.</computeroutput></term>
+ <listitem>
+ <para>
+ If you have an explicit transaction block in progress you cannot call
+ <command>CREATE DATABASE</command>. You must finish the transaction first.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>ERROR: Unable to create database directory 'xxx'.</computeroutput></term>
+ <term><computeroutput>ERROR: Could not initialize database directory.</computeroutput></term>
+ <listitem>
+ <para>
+ These are most likely related to insufficient permissions on the data
+ directory, a full disk, or other file system problems. The user under
+ which the database server is running, must have access to the location.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</para>
</refsect2>
<refsect1 id="R1-SQL-CREATEDATABASE-1">
<refsect1info>
- <date>1998-04-15</date>
+ <date>1999-12-11</date>
</refsect1info>
<title>
Description
</title>
<para>
- <command>CREATE DATABASE</command> creates a new Postgres database.
- The creator becomes the administrator of the new database.
+ <command>CREATE DATABASE</command> creates a new
+ <productname>PostgreSQL</productname> database.
+ The creator becomes the owner of the new database.
</para>
<para>
- An alternate location can be specified as either an
- environment variable known to the backend server
- (e.g. '<envar>PGDATA2</envar>') or, if the server is built to
- allow it, as an absolute path name
- (e.g. '<filename>/usr/local/pgsql/data</filename>').
- In either case, the location must be pre-configured
- by <command>initlocation</command>.
+ An alternate location can be specified in order to,
+ for example, store the database on a different disk.
+ The path must have been prepared with the <xref
+ linkend="APP-INITLOCATION" endterm="APP-INITLOCATION-title">
+ command.
+ </para>
+ <para>
+ If the path contains a slash, the leading part is interpreted
+ as an environment variable, which must be known to the
+ server process. This way the database administrator can
+ exercise control over at which locations databases can be created.
+ (A customary choice is, e.g., '<envar>PGDATA2</envar>'.)
+ If the server is compiled with <literal>ALLOW_ABSOLUTE_DBPATHS</literal>
+ (not so by default), absolute path names, as identified by
+ a leading slash
+ (e.g. '<filename>/usr/local/pgsql/data</filename>'),
+ are allowed as well.
</para>
<refsect2 id="R2-SQL-CREATEDATABASE-3">
<refsect2info>
- <date>1998-04-15</date>
+ <date>1999-12-11</date>
</refsect2info>
<title>
Notes
language extension.
</para>
<para>
- Use <command>DROP DATABASE</command> to remove a database.
+ Use <xref linkend="SQL-DROPDATABASE" endterm="SQL-DROPDATABASE-title"> to remove a database.
+ </para>
+ <para>
+ The program <xref linkend="APP-CREATEDB" endterm="APP-CREATEDB-title"> is a
+ shell script wrapper around this command, provided for convenience.
</para>
<para>
<prompt>$</prompt> <userinput>initlocation ~/private_db</userinput>
<computeroutput>Creating Postgres database system directory /home/olly/private_db/base</computeroutput>
- <prompt>$</prompt> <userinput>psql olly</userinput>
- <computeroutput>Welcome to psql, the PostgreSQL interactive terminal.
+<prompt>$</prompt> <userinput>psql olly</userinput>
+<computeroutput>Welcome to psql, the PostgreSQL interactive terminal.
(Please type \copyright to see the distribution terms of PostgreSQL.)
Type \h for help with SQL commands,
\? for help on internal slash commands,
\q to quit,
\g or terminate with semicolon to execute query.
- <prompt>olly=></prompt></computeroutput> <userinput>create database elsewhere with location = '/home/olly/private_db';</userinput>
- <computeroutput>CREATE DATABASE</computeroutput>
+<prompt>olly=></prompt></computeroutput> <userinput>CREATE DATABASE elsewhere WITH LOCATION = '/home/olly/private_db';</userinput>
+<computeroutput>CREATE DATABASE</computeroutput>
</programlisting>
</para>
</refsect1>
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_database.sgml,v 1.8 1999/12/04 04:53:15 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_database.sgml,v 1.9 1999/12/12 05:15:09 momjian Exp $
Postgres documentation
-->
DROP DATABASE
</refname>
<refpurpose>
- Destroys an existing database
+ Removes an existing database
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<refsynopsisdivinfo>
- <date>1999-07-20</date>
+ <date>1999-12-11</date>
</refsynopsisdivinfo>
<synopsis>
DROP DATABASE <replaceable class="PARAMETER">name</replaceable>
<refsect2 id="R2-SQL-DROPDATABASE-1">
<refsect2info>
- <date>1998-04-15</date>
+ <date>1999-12-11</date>
</refsect2info>
<title>
Inputs
<refsect2 id="R2-SQL-DROPDATABASE-2">
<refsect2info>
- <date>1998-04-15</date>
+ <date>1999-12-11</date>
</refsect2info>
<title>
Outputs
<para>
<variablelist>
+
<varlistentry>
- <term><computeroutput>
-DROP DATABASE
- </computeroutput></term>
+ <term><computeroutput>DROP DATABASE</computeroutput></term>
<listitem>
<para>
This message is returned if the command is successful.
</para>
</listitem>
</varlistentry>
+
<varlistentry>
- <term><computeroutput>
-WARN: destroydb: database "<replaceable class="parameter">name</replaceable>" does not exist.
- </computeroutput></term>
+ <term><computeroutput>ERROR: user '<replaceable class="parameter">username</replaceable>' is not allowed to create/drop databases</computeroutput></term>
<listitem>
<para>
- This message occurs if the specified database does not exist.
+ You must have the special CREATEDB privilege to drop databases.
+ See <xref linkend="SQL-CREATEUSER" endterm="SQL-CREATEUSER-title">.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>ERROR: dropdb: cannot be executed on the template database</computeroutput></term>
+ <listitem>
+ <para>
+ The <literal>template1</literal> database cannot be removed. It's not in
+ your interest.
</para>
</listitem>
</varlistentry>
+
<varlistentry>
- <term><computeroutput>
- ERROR: destroydb cannot be executed on an open database
- </computeroutput></term>
+ <term><computeroutput>ERROR: dropdb: cannot be executed on an open database</computeroutput></term>
+ <listitem>
+ <para>
+ You cannot be connected to the the database your are about to remove.
+ Instead, you could connect to <literal>template1</literal> or any other
+ database and run this command again.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>ERROR: dropdb: database '<replaceable class="parameter">name</replaceable>' does not exist</computeroutput></term>
<listitem>
<para>
This message occurs if the specified database does not exist.
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>ERROR: dropdb: database '<replaceable class="parameter">name</replaceable>' is not owned by you</computeroutput></term>
+ <listitem>
+ <para>
+ You must be the owner of the database. Being the owner usually means that
+ you created it as well.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>ERROR: dropdb: May not be called in a transaction block.</computeroutput></term>
+ <listitem>
+ <para>
+ You must finish the transaction in progress before you can call this command.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>NOTICE: The database directory 'xxx' could not be removed.</computeroutput></term>
+ <listitem>
+ <para>
+ The database was dropped (unless other error messages came up), but the
+ directory where the data is stored could not be removed. You must delete
+ it manually.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</para>
</refsect2>
<refsect1 id="R1-SQL-DROPDATABASE-1">
<refsect1info>
- <date>1998-04-15</date>
+ <date>1999-12-11</date>
</refsect1info>
<title>
Description
<para>
<command>DROP DATABASE</command> removes the catalog entries for an existing
database and deletes the directory containing the data.
- It can only be executed by the database administrator
- (See the <command>CREATE DATABASE</command> command for details).
+ It can only be executed by the database owner (usually the user that created
+ it).
</para>
<refsect2 id="R2-SQL-DROPDATABASE-3">
<refsect2info>
- <date>1998-04-15</date>
+ <date>1999-12-11</date>
</refsect2info>
<title>
Notes
</title>
<para>
- This query cannot be executed while connected to the target
- database. Thus, it might be more convenient to use
- <xref linkend="app-dropdb" endterm="app-dropdb-title">
- from the shell instead.
+ This command cannot be executed while connected to the target
+ database. Thus, it might be more convenient to use the shell
+ script <xref linkend="app-dropdb" endterm="app-dropdb-title">,
+ which is a wrapper around this command, instead.
</para>
<para>
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.46 1999/12/10 03:55:49 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.47 1999/12/12 05:15:10 momjian Exp $
*
*-------------------------------------------------------------------------
*/
char *lp,
loc[MAXPGPATH];
+ /* no single quotes in dbname */
+ if (strchr(dbname, '\'') != NULL)
+ elog(ERROR, "Single quotes are not allowed in database names.");
+ if (dbpath && strchr(dbpath, '\'') != NULL)
+ elog(ERROR, "Single quotes are not allowed in database paths.");
+
/*
* If this call returns, the database does not exist and we're allowed
* to create databases.
/* close virtual file descriptors so we can do system() calls */
closeAllVfds();
- /* Now create directory for this new database */
+ /* Make directory name for this new database */
if ((dbpath != NULL) && (strcmp(dbpath, dbname) != 0))
{
if (*(dbpath + strlen(dbpath) - 1) == SEP_CHAR)
lp = ExpandDatabasePath(loc);
if (lp == NULL)
- elog(ERROR, "Unable to locate path '%s'"
- "\n\tThis may be due to a missing environment variable"
- " in the server", loc);
+ elog(ERROR, "The path '%s' is invalid.\n"
+ "This may be due to a missing environment variable"
+ " on the server.", loc);
- if (mkdir(lp, S_IRWXU) != 0)
- elog(ERROR, "Unable to create database directory '%s'", lp);
+ /* no single quotes in expanded path */
+ if (strchr(lp, '\'') != NULL)
+ elog(ERROR, "Single quotes are not allowed in database paths.");
- snprintf(buf, sizeof(buf), "%s %s%cbase%ctemplate1%c* '%s'",
- COPY_CMD, DataDir, SEP_CHAR, SEP_CHAR, SEP_CHAR, lp);
- system(buf);
+ /* don't call this in a transaction block */
+ if (IsTransactionBlock())
+ elog(ERROR, "createdb: May not be called in a transaction block.");
+ else
+ BeginTransactionBlock();
snprintf(buf, sizeof(buf),
- "insert into pg_database (datname, datdba, encoding, datpath)"
- " values ('%s', '%d', '%d', '%s');", dbname, user_id, encoding,
- loc);
+ "INSERT INTO pg_database (datname, datdba, encoding, datpath)"
+ " VALUES ('%s', '%d', '%d', '%s')", dbname, user_id, encoding, loc);
pg_exec_query_dest(buf, dest, false);
+
+ if (mkdir(lp, S_IRWXU) != 0) {
+ UserAbortTransactionBlock();
+ elog(ERROR, "Unable to create database directory '%s'.", lp);
+ }
+
+ snprintf(buf, sizeof(buf), "%s %s%cbase%ctemplate1%c* '%s'",
+ COPY_CMD, DataDir, SEP_CHAR, SEP_CHAR, SEP_CHAR, lp);
+ if (system(buf) != 0) {
+ rmdir(lp);
+ UserAbortTransactionBlock();
+ elog(ERROR, "Could not initialize database directory.");
+ }
+
+ if (IsTransactionBlock())
+ EndTransactionBlock();
}
+
+
void
dropdb(char *dbname, CommandDest dest)
{
ScanKeyData key;
HeapTuple tup;
+ /* no single quotes in dbname */
+ if (strchr(dbname, '\'') != NULL)
+ elog(ERROR, "Single quotes are not allowed in database names.");
+
/*
* If this call returns, the database exists and we're allowed to
* remove it.
path = ExpandDatabasePath(dbpath);
if (path == NULL)
- elog(ERROR, "Unable to locate path '%s'"
- "\n\tThis may be due to a missing environment variable"
- " in the server", dbpath);
+ elog(ERROR, "The path '%s' is invalid.\n"
+ "This may be due to a missing environment variable"
+ " on the server.", path);
/* stop the vacuum daemon (dead code...) */
stop_vacuum(dbpath, dbname);
+ /* don't call this in a transaction block */
+ if (IsTransactionBlock())
+ elog(ERROR, "dropdb: May not be called in a transaction block.");
+ else
+ BeginTransactionBlock();
+
/*
* Obtain exclusive lock on pg_database. We need this to ensure
* that no new backend starts up in the target database while we
/*
* Check for active backends in the target database.
*/
- if (DatabaseHasActiveBackends(db_id))
- elog(ERROR, "Database '%s' has running backends, can't destroy it",
+ if (DatabaseHasActiveBackends(db_id)) {
+ heap_close(pgdbrel, AccessExclusiveLock);
+ UserAbortTransactionBlock();
+ elog(ERROR, "Database '%s' has running backends, can't drop it.",
dbname);
+ }
/*
* Find the database's tuple by OID (should be unique, we trust).
if (!HeapTupleIsValid(tup))
{
heap_close(pgdbrel, AccessExclusiveLock);
+ UserAbortTransactionBlock();
elog(ERROR, "Database '%s', OID %u, not found in pg_database",
dbname, db_id);
}
/*
* Remove the database's subdirectory and everything in it.
*/
- snprintf(buf, sizeof(buf), "rm -r '%s'", path);
- system(buf);
+ snprintf(buf, sizeof(buf), "rm -rf '%s'", path);
+ if (system(buf)!=0)
+ elog(NOTICE, "The database directory '%s' could not be removed.", path);
+
+ if (IsTransactionBlock())
+ EndTransactionBlock();
}
+
+
static HeapTuple
get_pg_dbtup(char *command, char *dbname, Relation dbrel)
{
/* Check to make sure user has permission to use createdb */
if (!use_createdb)
{
- elog(ERROR, "user '%s' is not allowed to create/destroy databases",
+ elog(ERROR, "user '%s' is not allowed to create/drop databases",
userName);
}