/*-------------------------------------------------------------------------
*
* connectdb . c
* This is a common file connection to the database .
*
* Portions Copyright ( c ) 1996 - 2025 , PostgreSQL Global Development Group
* Portions Copyright ( c ) 1994 , Regents of the University of California
*
* IDENTIFICATION
* src / bin / pg_dump / connectdb . c
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#include "postgres_fe.h"
#include "common/connect.h"
#include "common/logging.h"
#include "common/string.h"
#include "connectdb.h"
#include "dumputils.h"
#include "fe_utils/string_utils.h"
static char *constructConnStr(const char **keywords, const char **values);
/*
* ConnectDatabase
*
* Make a database connection with the given parameters . An
* interactive password prompt is automatically issued if required .
*
* If fail_on_error is false , we return NULL without printing any message
* on failure , but preserve any prompted password for the next try .
*
* On success , the ' connstr ' is set to a connection string containing
* the options used and ' server_version ' is set to version so that caller
* can use them .
*/
PGconn *
ConnectDatabase(const char *dbname, const char *connection_string,
const char *pghost, const char *pgport, const char *pguser,
trivalue prompt_password, bool fail_on_error, const char *progname,
const char **connstr, int *server_version, char *password,
char *override_dbname)
{
PGconn *conn;
bool new_pass;
const char *remoteversion_str;
int my_version;
const char **keywords = NULL;
const char **values = NULL;
PQconninfoOption *conn_opts = NULL;
int server_version_temp;
if (prompt_password == TRI_YES && !password)
password = simple_prompt("Password: " , false );
/*
* Start the connection . Loop until we have a password if requested by
* backend .
*/
do
{
int argcount = 8 ;
PQconninfoOption *conn_opt;
char *err_msg = NULL;
int i = 0 ;
free(keywords);
free(values);
PQconninfoFree(conn_opts);
/*
* Merge the connection info inputs given in form of connection string
* and other options . Explicitly discard any dbname value in the
* connection string ; otherwise , PQconnectdbParams ( ) would interpret
* that value as being itself a connection string .
*/
if (connection_string)
{
conn_opts = PQconninfoParse(connection_string, &err_msg);
if (conn_opts == NULL)
pg_fatal("%s" , err_msg);
for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
{
if (conn_opt->val != NULL && conn_opt->val[0 ] != '\0' &&
strcmp(conn_opt->keyword, "dbname" ) != 0 )
argcount++;
}
keywords = pg_malloc0((argcount + 1 ) * sizeof (*keywords));
values = pg_malloc0((argcount + 1 ) * sizeof (*values));
for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
{
if (conn_opt->val != NULL && conn_opt->val[0 ] != '\0' &&
strcmp(conn_opt->keyword, "dbname" ) != 0 )
{
keywords[i] = conn_opt->keyword;
values[i] = conn_opt->val;
i++;
}
}
}
else
{
keywords = pg_malloc0((argcount + 1 ) * sizeof (*keywords));
values = pg_malloc0((argcount + 1 ) * sizeof (*values));
}
if (pghost)
{
keywords[i] = "host" ;
values[i] = pghost;
i++;
}
if (pgport)
{
keywords[i] = "port" ;
values[i] = pgport;
i++;
}
if (pguser)
{
keywords[i] = "user" ;
values[i] = pguser;
i++;
}
if (password)
{
keywords[i] = "password" ;
values[i] = password;
i++;
}
if (dbname)
{
keywords[i] = "dbname" ;
values[i] = dbname;
i++;
}
if (override_dbname)
{
keywords[i] = "dbname" ;
values[i] = override_dbname;
i++;
}
keywords[i] = "fallback_application_name" ;
values[i] = progname;
i++;
new_pass = false ;
conn = PQconnectdbParams(keywords, values, true );
if (!conn)
pg_fatal("could not connect to database \" %s\"" , dbname);
if (PQstatus(conn) == CONNECTION_BAD &&
PQconnectionNeedsPassword(conn) &&
!password &&
prompt_password != TRI_NO)
{
PQfinish(conn);
password = simple_prompt("Password: " , false );
new_pass = true ;
}
} while (new_pass);
/* check to see that the backend connection was successfully made */
if (PQstatus(conn) == CONNECTION_BAD)
{
if (fail_on_error)
pg_fatal("%s" , PQerrorMessage(conn));
else
{
PQfinish(conn);
free(keywords);
free(values);
PQconninfoFree(conn_opts);
return NULL;
}
}
/*
* Ok , connected successfully . If requested , remember the options used , in
* the form of a connection string .
*/
if (connstr)
*connstr = constructConnStr(keywords, values);
free(keywords);
free(values);
PQconninfoFree(conn_opts);
/* Check version */
remoteversion_str = PQparameterStatus(conn, "server_version" );
if (!remoteversion_str)
pg_fatal("could not get server version" );
server_version_temp = PQserverVersion(conn);
if (server_version_temp == 0 )
pg_fatal("could not parse server version \" %s\"" ,
remoteversion_str);
/* If requested, then copy server version to out variable. */
if (server_version)
*server_version = server_version_temp;
my_version = PG_VERSION_NUM;
/*
* We allow the server to be back to 9 . 2 , and up to any minor release of
* our own major version . ( See also version check in pg_dump . c . )
*/
if (my_version != server_version_temp
&& (server_version_temp < 90200 ||
(server_version_temp / 100 ) > (my_version / 100 )))
{
pg_log_error("aborting because of server version mismatch" );
pg_log_error_detail("server version: %s; %s version: %s" ,
remoteversion_str, progname, PG_VERSION);
exit_nicely(1 );
}
PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL));
return conn;
}
/*
* constructConnStr
*
* Construct a connection string from the given keyword / value pairs . It is
* used to pass the connection options to the pg_dump subprocess .
*
* The following parameters are excluded :
* dbname - varies in each pg_dump invocation
* password - it ' s not secure to pass a password on the command line
* fallback_application_name - we ' ll let pg_dump set it
*/
static char *
constructConnStr(const char **keywords, const char **values)
{
PQExpBuffer buf = createPQExpBuffer();
char *connstr;
int i;
bool firstkeyword = true ;
/* Construct a new connection string in key='value' format. */
for (i = 0 ; keywords[i] != NULL; i++)
{
if (strcmp(keywords[i], "dbname" ) == 0 ||
strcmp(keywords[i], "password" ) == 0 ||
strcmp(keywords[i], "fallback_application_name" ) == 0 )
continue ;
if (!firstkeyword)
appendPQExpBufferChar(buf, ' ' );
firstkeyword = false ;
appendPQExpBuffer(buf, "%s=" , keywords[i]);
appendConnStrVal(buf, values[i]);
}
connstr = pg_strdup(buf->data);
destroyPQExpBuffer(buf);
return connstr;
}
/*
* executeQuery
*
* Run a query , return the results , exit program on failure .
*/
PGresult *
executeQuery(PGconn *conn, const char *query)
{
PGresult *res;
pg_log_info("executing %s" , query);
res = PQexec(conn, query);
if (!res ||
PQresultStatus(res) != PGRES_TUPLES_OK)
{
pg_log_error("query failed: %s" , PQerrorMessage(conn));
pg_log_error_detail("Query was: %s" , query);
PQfinish(conn);
exit_nicely(1 );
}
return res;
}
Messung V0.5 in Prozent C=97 H=90 G=93
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-08-07)
¤
*© Formatika GbR, Deutschland