/*-------------------------------------------------------------------------
*
* common . c
* Common support routines for bin / scripts /
*
*
* Portions Copyright ( c ) 1996 - 2025 , PostgreSQL Global Development Group
* Portions Copyright ( c ) 1994 , Regents of the University of California
*
* src / bin / scripts / common . c
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#include "postgres_fe.h"
#include <signal.h>
#include <unistd.h>
#include "common.h"
#include "common/connect.h"
#include "common/logging.h"
#include "common/string.h"
#include "fe_utils/query_utils.h"
#include "fe_utils/string_utils.h"
/*
* Split TABLE [ ( COLUMNS ) ] into TABLE and [ ( COLUMNS ) ] portions . When you
* finish using them , pg_free ( * table ) . * columns is a pointer into " spec " ,
* possibly to its NUL terminator .
*/
void
splitTableColumnsSpec(const char *spec, int encoding,
char **table, const char **columns)
{
bool inquotes = false ;
const char *cp = spec;
/*
* Find the first ' ( ' not identifier - quoted . Based on
* dequote_downcase_identifier ( ) .
*/
while (*cp && (*cp != '(' || inquotes))
{
if (*cp == '"' )
{
if (inquotes && cp[1 ] == '"' )
cp++; /* pair does not affect quoting */
else
inquotes = !inquotes;
cp++;
}
else
cp += PQmblenBounded(cp, encoding);
}
*table = pnstrdup(spec, cp - spec);
*columns = cp;
}
/*
* Break apart TABLE [ ( COLUMNS ) ] of " spec " . With the reset_val of search_path
* in effect , have regclassin ( ) interpret the TABLE portion . Append to " buf "
* the qualified name of TABLE , followed by any ( COLUMNS ) . Exit on failure .
* We use this to interpret - - table = foo under the search path psql would get ,
* in advance of " ANALYZE public . foo " under the always - secure search path .
*/
void
appendQualifiedRelation(PQExpBuffer buf, const char *spec,
PGconn *conn, bool echo)
{
char *table;
const char *columns;
PQExpBufferData sql;
PGresult *res;
int ntups;
splitTableColumnsSpec(spec, PQclientEncoding(conn), &table, &columns);
/*
* Query must remain ABSOLUTELY devoid of unqualified names . This would
* be unnecessary given a regclassin ( ) variant taking a search_path
* argument .
*/
initPQExpBuffer(&sql);
appendPQExpBufferStr(&sql,
"SELECT c.relname, ns.nspname\n"
" FROM pg_catalog.pg_class c,"
" pg_catalog.pg_namespace ns\n"
" WHERE c.relnamespace OPERATOR(pg_catalog.=) ns.oid\n"
" AND c.oid OPERATOR(pg_catalog.=) " );
appendStringLiteralConn(&sql, table, conn);
appendPQExpBufferStr(&sql, "::pg_catalog.regclass;" );
executeCommand(conn, "RESET search_path;" , echo);
/*
* One row is a typical result , as is a nonexistent relation ERROR .
* regclassin ( ) unconditionally accepts all - digits input as an OID ; if no
* relation has that OID ; this query returns no rows . Catalog corruption
* might elicit other row counts .
*/
res = executeQuery(conn, sql.data, echo);
ntups = PQntuples(res);
if (ntups != 1 )
{
pg_log_error(ngettext("query returned %d row instead of one: %s" ,
"query returned %d rows instead of one: %s" ,
ntups),
ntups, sql.data);
PQfinish(conn);
exit (1 );
}
appendPQExpBufferStr(buf,
fmtQualifiedIdEnc(PQgetvalue(res, 0 , 1 ),
PQgetvalue(res, 0 , 0 ),
PQclientEncoding(conn)));
appendPQExpBufferStr(buf, columns);
PQclear(res);
termPQExpBuffer(&sql);
pg_free(table);
PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, echo));
}
/*
* Check yes / no answer in a localized way . 1 = yes , 0 = no , - 1 = neither .
*/
/* translator: abbreviation for "yes" */
#define PG_YESLETTER gettext_noop("y" )
/* translator: abbreviation for "no" */
#define PG_NOLETTER gettext_noop("n" )
bool
yesno_prompt(const char *question)
{
char prompt[256 ];
/*------
translator : This is a question followed by the translated options for
"yes" and "no". */
snprintf(prompt, sizeof (prompt), _("%s (%s/%s) " ),
_(question), _(PG_YESLETTER), _(PG_NOLETTER));
for (;;)
{
char *resp;
resp = simple_prompt(prompt, true );
if (strcmp(resp, _(PG_YESLETTER)) == 0 )
{
free(resp);
return true ;
}
if (strcmp(resp, _(PG_NOLETTER)) == 0 )
{
free(resp);
return false ;
}
free(resp);
printf(_("Please answer \" %s\" or \" %s\".\n" ),
_(PG_YESLETTER), _(PG_NOLETTER));
}
}
Messung V0.5 in Prozent C=93 H=96 G=94
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland