Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions | Variables

common.h File Reference

#include "postgres_fe.h"
#include <setjmp.h>
#include "libpq-fe.h"
Include dependency graph for common.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define atooid(x)   ((Oid) strtoul((x), NULL, 10))

Functions

bool setQFout (const char *fname)
void psql_error (const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE
void void NoticeProcessor (void *arg, const char *message)
void setup_cancel_handler (void)
void SetCancelConn (void)
void ResetCancelConn (void)
PGresultPSQLexec (const char *query, bool start_xact)
bool SendQuery (const char *query)
bool is_superuser (void)
bool standard_strings (void)
const char * session_username (void)
void expand_tilde (char **filename)

Variables

volatile bool sigint_interrupt_enabled
sigjmp_buf sigint_interrupt_jmp
volatile bool cancel_pressed

Define Documentation

#define atooid (   x  )     ((Oid) strtoul((x), NULL, 10))

Definition at line 15 of file common.h.


Function Documentation

void expand_tilde ( char **  filename  ) 

Definition at line 1649 of file common.c.

References free, get_home_path(), NULL, pg_malloc(), and strlcpy().

Referenced by exec_command(), initializeInput(), parse_slash_copy(), and process_psqlrc().

{
    if (!filename || !(*filename))
        return;

    /*
     * WIN32 doesn't use tilde expansion for file names. Also, it uses tilde
     * for short versions of long file names, though the tilde is usually
     * toward the end, not at the beginning.
     */
#ifndef WIN32

    /* try tilde expansion */
    if (**filename == '~')
    {
        char       *fn;
        char        oldp,
                   *p;
        struct passwd *pw;
        char        home[MAXPGPATH];

        fn = *filename;
        *home = '\0';

        p = fn + 1;
        while (*p != '/' && *p != '\0')
            p++;

        oldp = *p;
        *p = '\0';

        if (*(fn + 1) == '\0')
            get_home_path(home);    /* ~ or ~/ only */
        else if ((pw = getpwnam(fn + 1)) != NULL)
            strlcpy(home, pw->pw_dir, sizeof(home));    /* ~user */

        *p = oldp;
        if (strlen(home) != 0)
        {
            char       *newfn;

            newfn = pg_malloc(strlen(home) + strlen(p) + 1);
            strcpy(newfn, home);
            strcat(newfn, p);

            free(fn);
            *filename = newfn;
        }
    }
#endif

    return;
}

bool is_superuser ( void   ) 

Definition at line 1581 of file common.c.

References _psqlSettings::db, PQparameterStatus(), pset, and val.

Referenced by get_prompt(), and pg_stat_statements().

{
    const char *val;

    if (!pset.db)
        return false;

    val = PQparameterStatus(pset.db, "is_superuser");

    if (val && strcmp(val, "on") == 0)
        return true;

    return false;
}

void void NoticeProcessor ( void *  arg,
const char *  message 
)

Definition at line 117 of file common.c.

References psql_error().

Referenced by do_connect(), and main().

{
    (void) arg;                 /* not used */
    psql_error("%s", message);
}

void psql_error ( const char *  fmt,
  ... 
)
PGresult* PSQLexec ( const char *  query,
bool  start_xact 
)

Definition at line 440 of file common.c.

References _, AcceptResult(), _psqlSettings::autocommit, _psqlSettings::db, _psqlSettings::echo_hidden, _psqlSettings::logfile, PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQexec(), PQresultStatus(), PQTRANS_IDLE, PQtransactionStatus(), pset, PSQL_ECHO_HIDDEN_NOEXEC, PSQL_ECHO_HIDDEN_OFF, psql_error(), ResetCancelConn(), and SetCancelConn().

Referenced by add_tablespace_footer(), describeAggregates(), describeFunctions(), describeOneTableDetails(), describeOneTSConfig(), describeOneTSParser(), describeOperators(), describeRoles(), describeTableDetails(), describeTablespaces(), describeTypes(), do_lo_import(), do_lo_list(), do_watch(), exec_command(), fail_lo_xact(), finish_lo_xact(), listAllDbs(), listCasts(), listCollations(), listConversions(), listDbRoleSettings(), listDefaultACLs(), listDomains(), listEventTriggers(), listExtensionContents(), listExtensions(), listForeignDataWrappers(), listForeignServers(), listForeignTables(), listLanguages(), listOneExtensionContents(), listSchemas(), listTables(), listTSConfigs(), listTSConfigsVerbose(), listTSDictionaries(), listTSParsers(), listTSParsersVerbose(), listTSTemplates(), listUserMappings(), objectDescription(), permissionsList(), process_file(), and start_lo_xact().

{
    PGresult   *res;

    if (!pset.db)
    {
        psql_error("You are currently not connected to a database.\n");
        return NULL;
    }

    if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
    {
        printf(_("********* QUERY **********\n"
                 "%s\n"
                 "**************************\n\n"), query);
        fflush(stdout);
        if (pset.logfile)
        {
            fprintf(pset.logfile,
                    _("********* QUERY **********\n"
                      "%s\n"
                      "**************************\n\n"), query);
            fflush(pset.logfile);
        }

        if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
            return NULL;
    }

    SetCancelConn();

    if (start_xact &&
        !pset.autocommit &&
        PQtransactionStatus(pset.db) == PQTRANS_IDLE)
    {
        res = PQexec(pset.db, "BEGIN");
        if (PQresultStatus(res) != PGRES_COMMAND_OK)
        {
            psql_error("%s", PQerrorMessage(pset.db));
            PQclear(res);
            ResetCancelConn();
            return NULL;
        }
        PQclear(res);
    }

    res = PQexec(pset.db, query);

    ResetCancelConn();

    if (!AcceptResult(res))
    {
        PQclear(res);
        res = NULL;
    }

    return res;
}

void ResetCancelConn ( void   ) 

Definition at line 347 of file common.c.

References NULL, and PQfreeCancel().

Referenced by CheckConnection(), do_lo_export(), do_lo_import(), do_lo_unlink(), executeMaintenanceCommand(), ProcessResult(), PSQLexec(), and SendQuery().

{
    PGcancel   *oldCancelConn;

#ifdef WIN32
    EnterCriticalSection(&cancelConnLock);
#endif

    oldCancelConn = cancelConn;
    /* be sure handle_sigint doesn't use pointer while freeing */
    cancelConn = NULL;

    if (oldCancelConn != NULL)
        PQfreeCancel(oldCancelConn);

#ifdef WIN32
    LeaveCriticalSection(&cancelConnLock);
#endif
}

bool SendQuery ( const char *  query  ) 

Definition at line 840 of file common.c.

References _, _psqlSettings::autocommit, buf, command_no_begin(), ConnectionUp(), _psqlSettings::cur_cmd_interactive, _psqlSettings::db, _psqlSettings::echo, printTableOpt::encoding, _psqlSettings::encoding, ExecQueryUsingCursor(), _psqlSettings::fetch_count, free, _psqlSettings::gfname, _psqlSettings::gset_prefix, INSTR_TIME_GET_MILLISEC, INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, is_select_command(), _psqlSettings::logfile, NULL, _psqlSettings::on_error_rollback, pg_encoding_to_char(), PGRES_COMMAND_OK, _psqlSettings::popt, PQclear(), PQclientEncoding(), PQcmdStatus(), PQerrorMessage(), PQexec(), PQresultStatus(), PQTRANS_ACTIVE, PQTRANS_IDLE, PQTRANS_INERROR, PQTRANS_INTRANS, PQTRANS_UNKNOWN, PQtransactionStatus(), PrintNotifications(), PrintQueryResults(), ProcessResult(), pset, PSQL_ECHO_QUERIES, psql_error(), PSQL_ERROR_ROLLBACK_OFF, PSQL_ERROR_ROLLBACK_ON, ResetCancelConn(), SetCancelConn(), SetVariable(), _psqlSettings::singlestep, _psqlSettings::sversion, _psqlSettings::timing, printQueryOpt::topt, and _psqlSettings::vars.

Referenced by do_copy(), main(), and MainLoop().

{
    PGresult   *results;
    PGTransactionStatusType transaction_status;
    double      elapsed_msec = 0;
    bool        OK = false;
    bool        on_error_rollback_savepoint = false;
    static bool on_error_rollback_warning = false;

    if (!pset.db)
    {
        psql_error("You are currently not connected to a database.\n");
        goto sendquery_cleanup;
    }

    if (pset.singlestep)
    {
        char        buf[3];

        printf(_("***(Single step mode: verify command)*******************************************\n"
                 "%s\n"
                 "***(press return to proceed or enter x and return to cancel)********************\n"),
               query);
        fflush(stdout);
        if (fgets(buf, sizeof(buf), stdin) != NULL)
            if (buf[0] == 'x')
                goto sendquery_cleanup;
    }
    else if (pset.echo == PSQL_ECHO_QUERIES)
    {
        puts(query);
        fflush(stdout);
    }

    if (pset.logfile)
    {
        fprintf(pset.logfile,
                _("********* QUERY **********\n"
                  "%s\n"
                  "**************************\n\n"), query);
        fflush(pset.logfile);
    }

    SetCancelConn();

    transaction_status = PQtransactionStatus(pset.db);

    if (transaction_status == PQTRANS_IDLE &&
        !pset.autocommit &&
        !command_no_begin(query))
    {
        results = PQexec(pset.db, "BEGIN");
        if (PQresultStatus(results) != PGRES_COMMAND_OK)
        {
            psql_error("%s", PQerrorMessage(pset.db));
            PQclear(results);
            ResetCancelConn();
            goto sendquery_cleanup;
        }
        PQclear(results);
        transaction_status = PQtransactionStatus(pset.db);
    }

    if (transaction_status == PQTRANS_INTRANS &&
        pset.on_error_rollback != PSQL_ERROR_ROLLBACK_OFF &&
        (pset.cur_cmd_interactive ||
         pset.on_error_rollback == PSQL_ERROR_ROLLBACK_ON))
    {
        if (on_error_rollback_warning == false && pset.sversion < 80000)
        {
            psql_error("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n",
                       pset.sversion / 10000, (pset.sversion / 100) % 100);
            on_error_rollback_warning = true;
        }
        else
        {
            results = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint");
            if (PQresultStatus(results) != PGRES_COMMAND_OK)
            {
                psql_error("%s", PQerrorMessage(pset.db));
                PQclear(results);
                ResetCancelConn();
                goto sendquery_cleanup;
            }
            PQclear(results);
            on_error_rollback_savepoint = true;
        }
    }

    if (pset.fetch_count <= 0 || !is_select_command(query))
    {
        /* Default fetch-it-all-and-print mode */
        instr_time  before,
                    after;

        if (pset.timing)
            INSTR_TIME_SET_CURRENT(before);

        results = PQexec(pset.db, query);

        /* these operations are included in the timing result: */
        ResetCancelConn();
        OK = ProcessResult(&results);

        if (pset.timing)
        {
            INSTR_TIME_SET_CURRENT(after);
            INSTR_TIME_SUBTRACT(after, before);
            elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
        }

        /* but printing results isn't: */
        if (OK && results)
            OK = PrintQueryResults(results);
    }
    else
    {
        /* Fetch-in-segments mode */
        OK = ExecQueryUsingCursor(query, &elapsed_msec);
        ResetCancelConn();
        results = NULL;         /* PQclear(NULL) does nothing */
    }

    /* If we made a temporary savepoint, possibly release/rollback */
    if (on_error_rollback_savepoint)
    {
        const char *svptcmd = NULL;

        transaction_status = PQtransactionStatus(pset.db);

        switch (transaction_status)
        {
            case PQTRANS_INERROR:
                /* We always rollback on an error */
                svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint";
                break;

            case PQTRANS_IDLE:
                /* If they are no longer in a transaction, then do nothing */
                break;

            case PQTRANS_INTRANS:

                /*
                 * Do nothing if they are messing with savepoints themselves:
                 * If the user did RELEASE or ROLLBACK, our savepoint is gone.
                 * If they issued a SAVEPOINT, releasing ours would remove
                 * theirs.
                 */
                if (results &&
                    (strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 ||
                     strcmp(PQcmdStatus(results), "RELEASE") == 0 ||
                     strcmp(PQcmdStatus(results), "ROLLBACK") == 0))
                    svptcmd = NULL;
                else
                    svptcmd = "RELEASE pg_psql_temporary_savepoint";
                break;

            case PQTRANS_ACTIVE:
            case PQTRANS_UNKNOWN:
            default:
                OK = false;
                /* PQTRANS_UNKNOWN is expected given a broken connection. */
                if (transaction_status != PQTRANS_UNKNOWN || ConnectionUp())
                    psql_error("unexpected transaction status (%d)\n",
                               transaction_status);
                break;
        }

        if (svptcmd)
        {
            PGresult   *svptres;

            svptres = PQexec(pset.db, svptcmd);
            if (PQresultStatus(svptres) != PGRES_COMMAND_OK)
            {
                psql_error("%s", PQerrorMessage(pset.db));
                PQclear(svptres);
                OK = false;

                PQclear(results);
                ResetCancelConn();
                goto sendquery_cleanup;
            }
            PQclear(svptres);
        }
    }

    PQclear(results);

    /* Possible microtiming output */
    if (pset.timing)
        printf(_("Time: %.3f ms\n"), elapsed_msec);

    /* check for events that may occur during query execution */

    if (pset.encoding != PQclientEncoding(pset.db) &&
        PQclientEncoding(pset.db) >= 0)
    {
        /* track effects of SET CLIENT_ENCODING */
        pset.encoding = PQclientEncoding(pset.db);
        pset.popt.topt.encoding = pset.encoding;
        SetVariable(pset.vars, "ENCODING",
                    pg_encoding_to_char(pset.encoding));
    }

    PrintNotifications();

    /* perform cleanup that should occur after any attempted query */

sendquery_cleanup:

    /* reset \g's output-to-filename trigger */
    if (pset.gfname)
    {
        free(pset.gfname);
        pset.gfname = NULL;
    }

    /* reset \gset trigger */
    if (pset.gset_prefix)
    {
        free(pset.gset_prefix);
        pset.gset_prefix = NULL;
    }

    return OK;
}

const char* session_username ( void   ) 

Definition at line 1628 of file common.c.

References _psqlSettings::db, PQparameterStatus(), PQuser(), pset, and val.

Referenced by get_prompt().

{
    const char *val;

    if (!pset.db)
        return NULL;

    val = PQparameterStatus(pset.db, "session_authorization");
    if (val)
        return val;
    else
        return PQuser(pset.db);
}

void SetCancelConn ( void   ) 

Definition at line 317 of file common.c.

References _psqlSettings::db, NULL, PQfreeCancel(), PQgetCancel(), and pset.

Referenced by do_lo_export(), do_lo_import(), do_lo_unlink(), executeMaintenanceCommand(), ProcessResult(), PSQLexec(), and SendQuery().

{
    PGcancel   *oldCancelConn;

#ifdef WIN32
    EnterCriticalSection(&cancelConnLock);
#endif

    /* Free the old one if we have one */
    oldCancelConn = cancelConn;
    /* be sure handle_sigint doesn't use pointer while freeing */
    cancelConn = NULL;

    if (oldCancelConn != NULL)
        PQfreeCancel(oldCancelConn);

    cancelConn = PQgetCancel(pset.db);

#ifdef WIN32
    LeaveCriticalSection(&cancelConnLock);
#endif
}

bool setQFout ( const char *  fname  ) 

Definition at line 42 of file common.c.

References pqsignal(), pset, psql_error(), _psqlSettings::queryFout, _psqlSettings::queryFoutPipe, SIG_DFL, SIG_IGN, SIGPIPE, status(), and strerror().

Referenced by exec_command(), ExecQueryUsingCursor(), main(), parse_psql_options(), and PrintQueryTuples().

{
    bool        status = true;

    /* Close old file/pipe */
    if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
    {
        if (pset.queryFoutPipe)
            pclose(pset.queryFout);
        else
            fclose(pset.queryFout);
    }

    /* If no filename, set stdout */
    if (!fname || fname[0] == '\0')
    {
        pset.queryFout = stdout;
        pset.queryFoutPipe = false;
    }
    else if (*fname == '|')
    {
        pset.queryFout = popen(fname + 1, "w");
        pset.queryFoutPipe = true;
    }
    else
    {
        pset.queryFout = fopen(fname, "w");
        pset.queryFoutPipe = false;
    }

    if (!(pset.queryFout))
    {
        psql_error("%s: %s\n", fname, strerror(errno));
        pset.queryFout = stdout;
        pset.queryFoutPipe = false;
        status = false;
    }

    /* Direct signals */
#ifndef WIN32
    pqsignal(SIGPIPE, pset.queryFoutPipe ? SIG_IGN : SIG_DFL);
#endif

    return status;
}

void setup_cancel_handler ( void   ) 

Definition at line 203 of file common.c.

{
    pqsignal(SIGINT, handle_sigint);
}

bool standard_strings ( void   ) 

Definition at line 1604 of file common.c.

References _psqlSettings::db, PQparameterStatus(), pset, and val.

Referenced by parse_slash_copy().

{
    const char *val;

    if (!pset.db)
        return false;

    val = PQparameterStatus(pset.db, "standard_conforming_strings");

    if (val && strcmp(val, "on") == 0)
        return true;

    return false;
}


Variable Documentation

volatile bool cancel_pressed

Definition at line 151 of file common.c.

Referenced by do_watch(), handle_sigint(), handleCopyIn(), and MainLoop().