Make createlang and droplang proof against weird search_path settings
by forcing search_path to be just pg_catalog.
This commit is contained in:
parent
866ffc2fe3
commit
9a9328003d
|
@ -1,22 +1,28 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* Miscellaneous shared code
|
||||
* common.c
|
||||
* Common support routines for bin/scripts/
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.17 2005/02/22 04:41:30 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.18 2005/08/15 21:02:26 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres_fe.h"
|
||||
#include "common.h"
|
||||
#include "libpq-fe.h"
|
||||
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#ifndef HAVE_INT_OPTRESET
|
||||
int optreset;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Returns the current user name.
|
||||
|
@ -55,7 +61,8 @@ get_user_name(const char *progname)
|
|||
* options.
|
||||
*/
|
||||
void
|
||||
handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
|
||||
handle_help_version_opts(int argc, char *argv[],
|
||||
const char *fixed_progname, help_handler hlp)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
|
@ -79,7 +86,8 @@ handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, hel
|
|||
*/
|
||||
PGconn *
|
||||
connectDatabase(const char *dbname, const char *pghost, const char *pgport,
|
||||
const char *pguser, bool require_password, const char *progname)
|
||||
const char *pguser, bool require_password,
|
||||
const char *progname)
|
||||
{
|
||||
PGconn *conn;
|
||||
char *password = NULL;
|
||||
|
@ -146,8 +154,10 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
|
|||
if (!res ||
|
||||
PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
fprintf(stderr, _("%s: query failed: %s"), progname, PQerrorMessage(conn));
|
||||
fprintf(stderr, _("%s: query was: %s\n"), progname, query);
|
||||
fprintf(stderr, _("%s: query failed: %s"),
|
||||
progname, PQerrorMessage(conn));
|
||||
fprintf(stderr, _("%s: query was: %s\n"),
|
||||
progname, query);
|
||||
PQfinish(conn);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -156,6 +166,34 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* As above for a SQL command (which returns nothing).
|
||||
*/
|
||||
void
|
||||
executeCommand(PGconn *conn, const char *query,
|
||||
const char *progname, bool echo)
|
||||
{
|
||||
PGresult *res;
|
||||
|
||||
if (echo)
|
||||
printf("%s\n", query);
|
||||
|
||||
res = PQexec(conn, query);
|
||||
if (!res ||
|
||||
PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||
{
|
||||
fprintf(stderr, _("%s: query failed: %s"),
|
||||
progname, PQerrorMessage(conn));
|
||||
fprintf(stderr, _("%s: query was: %s\n"),
|
||||
progname, query);
|
||||
PQfinish(conn);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check yes/no answer in a localized way. 1=yes, 0=no, -1=neither.
|
||||
*/
|
||||
|
|
|
@ -1,24 +1,40 @@
|
|||
#include "postgres_fe.h"
|
||||
/*
|
||||
* common.h
|
||||
* Common support routines for bin/scripts/
|
||||
*
|
||||
* Copyright (c) 2003-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/scripts/common.h,v 1.11 2005/08/15 21:02:26 tgl Exp $
|
||||
*/
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include "libpq-fe.h"
|
||||
#include "pqexpbuffer.h"
|
||||
#include "getopt_long.h"
|
||||
|
||||
#ifndef HAVE_INT_OPTRESET
|
||||
int optreset;
|
||||
extern int optreset;
|
||||
#endif
|
||||
|
||||
const char *get_user_name(const char *progname);
|
||||
typedef void (*help_handler) (const char *progname);
|
||||
|
||||
typedef void (*help_handler) (const char *);
|
||||
extern const char *get_user_name(const char *progname);
|
||||
|
||||
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp);
|
||||
extern void handle_help_version_opts(int argc, char *argv[],
|
||||
const char *fixed_progname,
|
||||
help_handler hlp);
|
||||
|
||||
PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
|
||||
const char *pguser, bool require_password, const char *progname);
|
||||
extern PGconn *connectDatabase(const char *dbname, const char *pghost,
|
||||
const char *pgport, const char *pguser,
|
||||
bool require_password, const char *progname);
|
||||
|
||||
PGresult *
|
||||
executeQuery(PGconn *conn, const char *command, const char *progname, bool echo);
|
||||
extern PGresult *executeQuery(PGconn *conn, const char *query,
|
||||
const char *progname, bool echo);
|
||||
|
||||
int
|
||||
check_yesno_response(const char *string);
|
||||
extern void executeCommand(PGconn *conn, const char *query,
|
||||
const char *progname, bool echo);
|
||||
|
||||
extern int check_yesno_response(const char *string);
|
||||
|
||||
#endif /* COMMON_H */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.18 2005/07/10 14:26:30 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.19 2005/08/15 21:02:26 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -138,11 +138,12 @@ main(int argc, char *argv[])
|
|||
{
|
||||
printQueryOpt popt;
|
||||
|
||||
conn = connectDatabase(dbname, host, port, username, password, progname);
|
||||
conn = connectDatabase(dbname, host, port, username, password,
|
||||
progname);
|
||||
|
||||
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE WHEN lanpltrusted "
|
||||
"THEN '%s' ELSE '%s' END) as \"%s\" FROM pg_language "
|
||||
"WHERE lanispl IS TRUE;",
|
||||
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
|
||||
"(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
|
||||
"FROM pg_catalog.pg_language WHERE lanispl;",
|
||||
_("Name"), _("yes"), _("no"), _("Trusted?"));
|
||||
result = executeQuery(conn, sql.data, progname, echo);
|
||||
|
||||
|
@ -221,6 +222,13 @@ main(int argc, char *argv[])
|
|||
|
||||
conn = connectDatabase(dbname, host, port, username, password, progname);
|
||||
|
||||
/*
|
||||
* Force schema search path to be just pg_catalog, so that we don't
|
||||
* have to be paranoid about search paths below.
|
||||
*/
|
||||
executeCommand(conn, "SET search_path = pg_catalog;",
|
||||
progname, echo);
|
||||
|
||||
/*
|
||||
* Make sure the language isn't already installed
|
||||
*/
|
||||
|
@ -232,8 +240,7 @@ main(int argc, char *argv[])
|
|||
{
|
||||
PQfinish(conn);
|
||||
fprintf(stderr,
|
||||
_("%s: language \"%s\" is already installed in "
|
||||
"database \"%s\"\n"),
|
||||
_("%s: language \"%s\" is already installed in database \"%s\"\n"),
|
||||
progname, langname, dbname);
|
||||
/* separate exit status for "already installed" */
|
||||
exit(2);
|
||||
|
@ -244,7 +251,8 @@ main(int argc, char *argv[])
|
|||
* Check whether the call handler exists
|
||||
*/
|
||||
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' "
|
||||
"AND prorettype = 'pg_catalog.language_handler'::regtype "
|
||||
"AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
|
||||
"AND prorettype = 'language_handler'::regtype "
|
||||
"AND pronargs = 0;", handler);
|
||||
result = executeQuery(conn, sql.data, progname, echo);
|
||||
handlerexists = (PQntuples(result) > 0);
|
||||
|
@ -255,9 +263,10 @@ main(int argc, char *argv[])
|
|||
*/
|
||||
if (validator)
|
||||
{
|
||||
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s'"
|
||||
" AND proargtypes[0] = 'pg_catalog.oid'::regtype "
|
||||
" AND pronargs = 1;", validator);
|
||||
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' "
|
||||
"AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
|
||||
"AND proargtypes[0] = 'oid'::regtype "
|
||||
"AND pronargs = 1;", validator);
|
||||
result = executeQuery(conn, sql.data, progname, echo);
|
||||
validatorexists = (PQntuples(result) > 0);
|
||||
PQclear(result);
|
||||
|
@ -267,27 +276,30 @@ main(int argc, char *argv[])
|
|||
|
||||
/*
|
||||
* Create the function(s) and the language
|
||||
*
|
||||
* NOTE: the functions will be created in pg_catalog because
|
||||
* of our previous "SET search_path".
|
||||
*/
|
||||
resetPQExpBuffer(&sql);
|
||||
|
||||
if (!handlerexists)
|
||||
appendPQExpBuffer(&sql,
|
||||
"CREATE FUNCTION pg_catalog.\"%s\" () RETURNS "
|
||||
"language_handler AS '%s/%s' LANGUAGE C;\n",
|
||||
"CREATE FUNCTION \"%s\" () RETURNS language_handler "
|
||||
"AS '%s/%s' LANGUAGE C;\n",
|
||||
handler, pglib, object);
|
||||
|
||||
if (!validatorexists)
|
||||
appendPQExpBuffer(&sql,
|
||||
"CREATE FUNCTION pg_catalog.\"%s\" (oid) RETURNS "
|
||||
"void AS '%s/%s' LANGUAGE C;\n",
|
||||
"CREATE FUNCTION \"%s\" (oid) RETURNS void "
|
||||
"AS '%s/%s' LANGUAGE C;\n",
|
||||
validator, pglib, object);
|
||||
|
||||
appendPQExpBuffer(&sql,
|
||||
"CREATE %sLANGUAGE \"%s\" HANDLER pg_catalog.\"%s\"",
|
||||
"CREATE %sLANGUAGE \"%s\" HANDLER \"%s\"",
|
||||
(trusted ? "TRUSTED " : ""), langname, handler);
|
||||
|
||||
if (validator)
|
||||
appendPQExpBuffer(&sql, " VALIDATOR pg_catalog.\"%s\"", validator);
|
||||
appendPQExpBuffer(&sql, " VALIDATOR \"%s\"", validator);
|
||||
|
||||
appendPQExpBuffer(&sql, ";\n");
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.16 2005/07/10 14:26:30 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.17 2005/08/15 21:02:26 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -140,9 +140,9 @@ main(int argc, char *argv[])
|
|||
conn = connectDatabase(dbname, host, port, username, password,
|
||||
progname);
|
||||
|
||||
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE "
|
||||
"WHEN lanpltrusted THEN '%s' ELSE '%s' END) "
|
||||
"as \"%s\" FROM pg_language WHERE lanispl IS TRUE;",
|
||||
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
|
||||
"(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
|
||||
"FROM pg_catalog.pg_language WHERE lanispl;",
|
||||
_("Name"), _("yes"), _("no"), _("Trusted?"));
|
||||
result = executeQuery(conn, sql.data, progname, echo);
|
||||
|
||||
|
@ -172,6 +172,13 @@ main(int argc, char *argv[])
|
|||
|
||||
conn = connectDatabase(dbname, host, port, username, password, progname);
|
||||
|
||||
/*
|
||||
* Force schema search path to be just pg_catalog, so that we don't
|
||||
* have to be paranoid about search paths below.
|
||||
*/
|
||||
executeCommand(conn, "SET search_path = pg_catalog;",
|
||||
progname, echo);
|
||||
|
||||
/*
|
||||
* Make sure the language is installed and find the OIDs of the
|
||||
* handler and validator functions
|
||||
|
@ -248,8 +255,8 @@ main(int argc, char *argv[])
|
|||
*/
|
||||
if (OidIsValid(lanvalidator))
|
||||
{
|
||||
printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language WHERE "
|
||||
"lanvalidator = %u AND lanname <> '%s';",
|
||||
printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language "
|
||||
"WHERE lanvalidator = %u AND lanname <> '%s';",
|
||||
lanvalidator, langname);
|
||||
result = executeQuery(conn, sql.data, progname, echo);
|
||||
if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)
|
||||
|
|
Loading…
Reference in New Issue